version 4.0.0 first support for new E2 ASN
[ric-plt/e2.git] / RIC-E2-TERMINATION / TEST / testAsn / httpServer / HttpServer.cpp
1 /*
2  * Copyright 2020 AT&T Intellectual Property
3  * Copyright 2020 Nokia
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 //
19 // Created by adi ENZEL on 2/16/20.
20 //
21
22 #include "HttpServer.h"
23 #include <algorithm>
24 #include <random>
25
26
27 #include "../sctpClient/sctpClient.h"
28
29 #include "../T1/E2Builder.h"
30 #include "../base64.h"
31
32 using namespace std;
33 using namespace Pistache;
34
35 #define RECEIVE_SCTP_BUFFER_SIZE 8192
36
37 namespace Generic {
38
39     void handleReady(const Rest::Request&, Http::ResponseWriter response) {
40         response.send(Http::Code::Ok, "1");
41     }
42 }
43
44
45     HttpServer::HttpServer(Address addr)
46             : httpBaseSocket(0), httpEndpoint(std::make_shared<Http::Endpoint>(addr)) { }
47
48     void HttpServer::init(size_t thr) {
49         if ((httpBaseSocket = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
50             fprintf(stderr, "Socket() error. %s\n", strerror(errno));
51             exit(-1);
52         }
53         auto optval = 1;
54         if (setsockopt(httpBaseSocket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof optval) != 0) {
55             fprintf(stderr, "setsockopt SO_REUSEPORT Error, %s %s, %d\n", strerror(errno), __func__, __LINE__);
56             close(httpBaseSocket);
57             exit(-1);
58         }
59         optval = 1;
60         if (setsockopt(httpBaseSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) != 0) {
61             fprintf(stderr, "setsockopt SO_REUSEADDR Error, %s %s, %d\n", strerror(errno), __func__, __LINE__);
62             close(httpBaseSocket);
63             exit(-1);
64         }
65
66         struct sockaddr_in address{};
67         address.sin_family = AF_INET;
68         if(inet_pton(AF_INET, "127.0.0.1", &address.sin_addr)<=0)
69         {
70             fprintf(stderr,"Invalid address/Address not supported. %s", strerror(errno));
71             exit(-1);
72         }
73
74
75         address.sin_port = htons(9098);
76         if (connect(httpBaseSocket, (SA *)(&address), sizeof(address)) < 0) {
77             fprintf(stderr, "connect() error. %s\n", strerror(errno));
78             exit(-1);
79         }
80         auto opts = Http::Endpoint::options().threads(thr);
81         httpEndpoint->init(opts);
82         setupRoutes();
83     }
84
85     void HttpServer::start() {
86         std::random_device device{};
87         std::mt19937 generator(device());
88         std::uniform_int_distribution<long> distribution(1, (long) 1e12);
89         transactionCounter = distribution(generator);
90
91
92         httpEndpoint->setHandler(router.handler());
93         httpEndpoint->serve();
94     }
95
96     void HttpServer::setupRoutes() {
97         using namespace Rest;
98
99         Routes::Get(router, "/setup/:ricaddress/:ricPort/:mcc/:mnc", Routes::bind(&HttpServer::sendSetupReq, this));
100         //Routes::Post(router, "/ricIndication/:ricid/:subscriptionId/:mcc/:mnc", Routes::bind(&HttpServer::sendSetupReq, this));
101         Routes::Get(router, "/ready", Routes::bind(&Generic::handleReady));
102     }
103
104
105     void HttpServer::sendSetupReq(const Rest::Request& request, Http::ResponseWriter response) {
106         auto mcc = request.param(":mcc").as<int>();
107         auto mnc = request.param(":mnc").as<int>();
108         auto ricAdress = request.param(":ricaddress").as<std::string>();
109         auto ricPort = request.param(":ricPort").as<int>();
110         //TODO  build setup to send to address
111         E2AP_PDU_t pdu;
112
113         buildSetupRequest(&pdu,mcc, mnc);
114         // encode PDU to PER
115
116         auto buffer_size =  RECEIVE_SCTP_BUFFER_SIZE;
117         unsigned char buffer[RECEIVE_SCTP_BUFFER_SIZE] = {};
118         // encode to xml
119         asn_enc_rval_t er;
120         er = asn_encode_to_buffer(0, ATS_ALIGNED_BASIC_PER, &asn_DEF_E2AP_PDU, &pdu, buffer, buffer_size);
121         if (er.encoded == -1) {
122            cerr << "encoding of : " <<  asn_DEF_E2AP_PDU.name << " failed, "<< strerror(errno) << endl;
123            response.send(Http::Code::Internal_Server_Error, "strerror(errno)");
124            return;
125         } else if (er.encoded > (ssize_t)buffer_size) {
126             cerr << "Buffer of size : " << buffer_size << " is to small for : " << asn_DEF_E2AP_PDU.name << endl;
127             response.send(Http::Code::Internal_Server_Error, "Buffer of size is too small");
128             return;
129         }
130
131         long len = er.encoded * 4 / 3 + 128;
132         auto *base64Buff = (unsigned char *)calloc(1,len + 1024);
133         char tx[32];
134         snprintf((char *) tx, sizeof tx, "%15ld", transactionCounter++);
135
136         auto sentLen = snprintf((char *)base64Buff, 1024, "%d|%s|%s|%d|", setupRequest_gnb, tx, ricAdress.c_str(), ricPort);
137
138         base64::encode(buffer, er.encoded, &base64Buff[sentLen], len);
139         sentLen += len;
140         len = send(httpBaseSocket, base64Buff, sentLen, 0);
141         if (len < 0) {
142             cerr << "failed sending setupRequest_gnb to Other thread. Error : " << strerror(errno) << endl;
143             response.send(Http::Code::Internal_Server_Error, "Failed send buffer");
144             free(base64Buff);
145             return;
146         }
147         char tx1[128];
148         snprintf((char *) tx1, sizeof tx1, "{\"id\": %s}", tx);
149         response.send(Http::Code::Ok, tx1);
150         free(base64Buff);
151     }