Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / SCTP / e2sim_sctp.cpp
1 /*****************************************************************************
2 #                                                                            *
3 # Copyright 2019 AT&T Intellectual Property                                  *
4 # Copyright 2019 Nokia                                                       *
5 #                                                                            *
6 # Licensed under the Apache License, Version 2.0 (the "License");            *
7 # you may not use this file except in compliance with the License.           *
8 # You may obtain a copy of the License at                                    *
9 #                                                                            *
10 #      http://www.apache.org/licenses/LICENSE-2.0                            *
11 #                                                                            *
12 # Unless required by applicable law or agreed to in writing, software        *
13 # distributed under the License is distributed on an "AS IS" BASIS,          *
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
15 # See the License for the specific language governing permissions and        *
16 # limitations under the License.                                             *
17 #                                                                            *
18 ******************************************************************************/
19 #include <stdio.h>
20 #include <string.h>
21 #include <unistd.h>             //for close()
22 #include <stdlib.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <netinet/sctp.h>
26 #include <arpa/inet.h>  //for inet_ntop()
27 #include <assert.h>
28
29 #include "e2sim_sctp.hpp"
30 // #include "e2sim_defs.h"
31
32
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/sctp.h>
36 #include <signal.h>
37 #include <unistd.h>
38 #include <string.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41
42 int sctp_start_server(const char *server_ip_str, const int server_port)
43 {
44   if(server_port < 1 || server_port > 65535) {
45       LOG_E("Invalid port number (%d). Valid values are between 1 and 65535.\n", server_port);
46       exit(1);
47   }
48
49   int server_fd, af;
50   struct sockaddr* server_addr;
51   size_t addr_len;
52
53   struct sockaddr_in  server4_addr;
54   memset(&server4_addr, 0, sizeof(struct sockaddr_in));
55
56   struct sockaddr_in6 server6_addr;
57   memset(&server6_addr, 0, sizeof(struct sockaddr_in6));
58
59   if(inet_pton(AF_INET, server_ip_str, &server4_addr.sin_addr) == 1)
60   {
61     server4_addr.sin_family = AF_INET;
62     server4_addr.sin_port   = htons(server_port);
63
64     server_addr = (struct sockaddr*)&server4_addr;
65     af          = AF_INET;
66     addr_len    = sizeof(server4_addr);
67   }
68   else if(inet_pton(AF_INET6, server_ip_str, &server6_addr.sin6_addr) == 1)
69   {
70     server6_addr.sin6_family = AF_INET6;
71     server6_addr.sin6_port   = htons(server_port);
72
73     server_addr = (struct sockaddr*)&server6_addr;
74     af          = AF_INET6;
75     addr_len    = sizeof(server6_addr);
76   }
77   else {
78     perror("inet_pton()");
79     exit(1);
80   }
81
82   if((server_fd = socket(af, SOCK_STREAM, IPPROTO_SCTP)) == -1) {
83     perror("socket");
84     exit(1);
85   }
86
87   //set send_buffer
88   // int sendbuff = 10000;
89   // socklen_t optlen = sizeof(sendbuff);
90   // if(getsockopt(server_fd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen) == -1) {
91   //   perror("getsockopt send");
92   //   exit(1);
93   // }
94   // else
95   //   LOG_D("[SCTP] send buffer size = %d\n", sendbuff);
96
97
98   if(bind(server_fd, server_addr, addr_len) == -1) {
99     perror("bind");
100     exit(1);
101   }
102
103   if(listen(server_fd, SERVER_LISTEN_QUEUE_SIZE) != 0) {
104     perror("listen");
105     exit(1);
106   }
107
108   assert(server_fd != 0);
109
110   LOG_I("[SCTP] Server started on %s:%d", server_ip_str, server_port);
111
112   return server_fd;
113 }
114
115 int sctp_start_client(const char *server_ip_str, const int server_port)
116 {
117   int client_fd, af;
118
119   struct sockaddr* server_addr;
120   size_t addr_len;
121
122   struct sockaddr_in  server4_addr;
123   memset(&server4_addr, 0, sizeof(struct sockaddr_in));
124
125   struct sockaddr_in6 server6_addr;
126   memset(&server6_addr, 0, sizeof(struct sockaddr_in6));
127
128   if(inet_pton(AF_INET, server_ip_str, &server4_addr.sin_addr) == 1)
129   {
130     server4_addr.sin_family = AF_INET;
131     server4_addr.sin_port   = htons(server_port);
132     server_addr = (struct sockaddr*)&server4_addr;
133     addr_len    = sizeof(server4_addr);
134   }
135   else if(inet_pton(AF_INET6, server_ip_str, &server6_addr.sin6_addr) == 1)
136   {
137     server6_addr.sin6_family = AF_INET6;
138     server6_addr.sin6_port   = htons(server_port);
139     server_addr = (struct sockaddr*)&server6_addr;
140     addr_len    = sizeof(server6_addr);
141   }
142   else {
143     perror("inet_pton()");
144     exit(1);
145   }
146
147   if((client_fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP)) == -1)
148   {
149      perror("socket");
150      exit(1);
151   }
152
153   // int sendbuff = 10000;
154   // socklen_t optlen = sizeof(sendbuff);
155   // if(getsockopt(client_fd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen) == -1) {
156   //   perror("getsockopt send");
157   //   exit(1);
158   // }
159   // else
160   //   LOG_D("[SCTP] send buffer size = %d\n", sendbuff);
161
162   //--------------------------------
163   //Bind before connect
164   auto optval = 1;
165   if( setsockopt(client_fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof optval) != 0 ){
166     perror("setsockopt port");
167     exit(1);
168   }
169
170   if( setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) != 0 ){
171     perror("setsockopt addr");
172     exit(1);
173   }
174
175   struct sockaddr_in6  client6_addr {};
176   client6_addr.sin6_family = AF_INET6;
177   client6_addr.sin6_port   = htons(RIC_SCTP_SRC_PORT);
178   client6_addr.sin6_addr   = in6addr_any;
179
180   LOG_I("[SCTP] Binding client socket to source port %d", RIC_SCTP_SRC_PORT);
181   if(bind(client_fd, (struct sockaddr*)&client6_addr, sizeof(client6_addr)) == -1) {
182     perror("bind");
183     exit(1);
184   }
185   // end binding ---------------------
186
187   LOG_I("[SCTP] Connecting to server at %s:%d ...", server_ip_str, server_port);
188   if(connect(client_fd, server_addr, addr_len) == -1) {
189     perror("connect");
190     exit(1);
191   }
192   assert(client_fd != 0);
193
194   LOG_I("[SCTP] Connection established");
195
196   return client_fd;
197 }
198
199 int sctp_accept_connection(const char *server_ip_str, const int server_fd)
200 {
201   LOG_I("[SCTP] Waiting for new connection...");
202
203   struct sockaddr client_addr;
204   socklen_t       client_addr_size;
205   int             client_fd;
206
207   //Blocking call
208   client_fd = accept(server_fd, &client_addr, &client_addr_size);
209   fprintf(stderr, "client fd is %d\n", client_fd);
210   if(client_fd == -1){
211     perror("accept()");
212     close(client_fd);
213     exit(1);
214   }
215
216   //Retrieve client IP_ADDR
217   char client_ip6_addr[INET6_ADDRSTRLEN], client_ip4_addr[INET_ADDRSTRLEN];
218   if(strchr(server_ip_str, ':') != NULL) //IPv6
219   {
220     struct sockaddr_in6* client_ipv6 = (struct sockaddr_in6*)&client_addr;
221     inet_ntop(AF_INET6, &(client_ipv6->sin6_addr), client_ip6_addr, INET6_ADDRSTRLEN);
222     LOG_I("[SCTP] New client connected from %s", client_ip6_addr);
223   }
224   else {
225     struct sockaddr_in* client_ipv4 = (struct sockaddr_in*)&client_addr;
226     inet_ntop(AF_INET, &(client_ipv4->sin_addr), client_ip4_addr, INET_ADDRSTRLEN);
227     LOG_I("[SCTP] New client connected from %s", client_ip4_addr);
228   }
229
230   return client_fd;
231 }
232
233 int sctp_send_data(int &socket_fd, sctp_buffer_t &data)
234 {
235   fprintf(stderr,"in sctp send data func\n");
236   fprintf(stderr,"data.len is %d", data.len);
237   int sent_len = send(socket_fd, (void*)(&(data.buffer[0])), data.len, 0);
238   fprintf(stderr,"after getting sent_len\n");
239
240   if(sent_len == -1) {
241     perror("[SCTP] sctp_send_data");
242     exit(1);
243   }
244
245   return sent_len;
246 }
247
248 int sctp_send_data_X2AP(int &socket_fd, sctp_buffer_t &data)
249 {
250   int sent_len = sctp_sendmsg(socket_fd, (void*)(&(data.buffer[0])), data.len,
251                   NULL, 0, (uint32_t) X2AP_PPID, 0, 0, 0, 0);
252
253   if(sent_len == -1) {
254     perror("[SCTP] sctp_send_data");
255     exit(1);
256   }
257
258 }
259
260 /*
261 Receive data from SCTP socket
262 Outcome of recv()
263 -1: exit the program
264 0: close the connection
265 +: new data
266 */
267 int sctp_receive_data(int &socket_fd, sctp_buffer_t &data)
268 {
269   //clear out the data before receiving
270   fprintf(stderr, "receive data1\n");
271   memset(data.buffer, 0, sizeof(data.buffer));
272   fprintf(stderr, "receive data2\n");  
273   data.len = 0;
274
275   //receive data from the socket
276   int recv_len = recv(socket_fd, &(data.buffer), sizeof(data.buffer), 0);
277   fprintf(stderr, "receive data3\n");
278   
279   if(recv_len == -1)
280   {
281     perror("[SCTP] recv");
282     exit(1);
283   }
284   else if (recv_len == 0)
285   {
286     LOG_I("[SCTP] Connection closed by remote peer");
287     if(close(socket_fd) == -1)
288     {
289       perror("[SCTP] close");
290     }
291     return -1;
292   }
293
294   data.len = recv_len;
295
296   return recv_len;
297 }