3d808c512bc61cc4cd4252d1bddb6bbe61fc23ee
[it/test.git] / simulators / e2sim / 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 int sctp_start_server(const char *server_ip_str, const int server_port)
33 {
34   if(server_port < 1 || server_port > 65535) {
35       LOG_E("Invalid port number (%d). Valid values are between 1 and 65535.\n", server_port);
36       exit(1);
37   }
38
39   int server_fd, af;
40   struct sockaddr* server_addr;
41   size_t addr_len;
42
43   struct sockaddr_in  server4_addr;
44   memset(&server4_addr, 0, sizeof(struct sockaddr_in));
45
46   struct sockaddr_in6 server6_addr;
47   memset(&server6_addr, 0, sizeof(struct sockaddr_in6));
48
49   if(inet_pton(AF_INET, server_ip_str, &server4_addr.sin_addr) == 1)
50   {
51     server4_addr.sin_family = AF_INET;
52     server4_addr.sin_port   = htons(server_port);
53
54     server_addr = (struct sockaddr*)&server4_addr;
55     af          = AF_INET;
56     addr_len    = sizeof(server4_addr);
57   }
58   else if(inet_pton(AF_INET6, server_ip_str, &server6_addr.sin6_addr) == 1)
59   {
60     server6_addr.sin6_family = AF_INET6;
61     server6_addr.sin6_port   = htons(server_port);
62
63     server_addr = (struct sockaddr*)&server6_addr;
64     af          = AF_INET6;
65     addr_len    = sizeof(server6_addr);
66   }
67   else {
68     perror("inet_pton()");
69     exit(1);
70   }
71
72   if((server_fd = socket(af, SOCK_STREAM, IPPROTO_SCTP)) == -1) {
73     perror("socket");
74     exit(1);
75   }
76
77   if(bind(server_fd, server_addr, addr_len) == -1) {
78     perror("bind");
79     exit(1);
80   }
81
82   if(listen(server_fd, SERVER_LISTEN_QUEUE_SIZE) != 0) {
83     perror("listen");
84     exit(1);
85   }
86
87   assert(server_fd != 0);
88
89   LOG_I("[SCTP] Server started on %s:%d", server_ip_str, server_port);
90
91   return server_fd;
92 }
93
94 int sctp_start_client(const char *server_ip_str, const int server_port)
95 {
96   int client_fd, af;
97
98   struct sockaddr* server_addr;
99   size_t addr_len;
100
101   struct sockaddr_in  server4_addr;
102   memset(&server4_addr, 0, sizeof(struct sockaddr_in));
103
104   struct sockaddr_in6 server6_addr;
105   memset(&server6_addr, 0, sizeof(struct sockaddr_in6));
106
107   if(inet_pton(AF_INET, server_ip_str, &server4_addr.sin_addr) == 1)
108   {
109     server4_addr.sin_family = AF_INET;
110     server4_addr.sin_port   = htons(server_port);
111
112     server_addr = (struct sockaddr*)&server4_addr;
113     af          = AF_INET;
114     addr_len    = sizeof(server4_addr);
115   }
116   else if(inet_pton(AF_INET6, server_ip_str, &server6_addr.sin6_addr) == 1)
117   {
118     server6_addr.sin6_family = AF_INET6;
119     server6_addr.sin6_port   = htons(server_port);
120
121     server_addr = (struct sockaddr*)&server6_addr;
122     af          = AF_INET6;
123     addr_len    = sizeof(server6_addr);
124   }
125   else {
126     perror("inet_pton()");
127     exit(1);
128   }
129
130   if((client_fd = socket(af, SOCK_STREAM, IPPROTO_SCTP)) == -1)
131   {
132      perror("socket");
133      exit(1);
134   }
135
136   LOG_I("[SCTP] Connecting to server at %s:%d ...", server_ip_str, server_port);
137
138   if(connect(client_fd, server_addr, addr_len) == -1) {
139     perror("connect");
140     exit(1);
141   }
142
143   assert(client_fd != 0);
144
145   LOG_I("[SCTP] Connection established");
146
147   return client_fd;
148
149 }
150
151 int sctp_accept_connection(const char *server_ip_str, const int server_fd)
152 {
153   LOG_I("[SCTP] Waiting for new connection...");
154
155   struct sockaddr client_addr;
156   socklen_t       client_addr_size;
157   int             client_fd;
158
159   //Blocking call
160   client_fd = accept(server_fd, &client_addr, &client_addr_size);
161   if(client_fd == -1){
162     perror("accept()");
163     close(client_fd);
164     exit(1);
165   }
166
167   //Retrieve client IP_ADDR
168   char client_ip6_addr[INET6_ADDRSTRLEN], client_ip4_addr[INET_ADDRSTRLEN];
169   if(strchr(server_ip_str, ':') != NULL) //IPv6
170   {
171     struct sockaddr_in6* client_ipv6 = (struct sockaddr_in6*)&client_addr;
172     inet_ntop(AF_INET6, &(client_ipv6->sin6_addr), client_ip6_addr, INET6_ADDRSTRLEN);
173     LOG_I("[SCTP] New client connected from %s", client_ip6_addr);
174   }
175   else {
176     struct sockaddr_in* client_ipv4 = (struct sockaddr_in*)&client_addr;
177     inet_ntop(AF_INET, &(client_ipv4->sin_addr), client_ip4_addr, INET_ADDRSTRLEN);
178     LOG_I("[SCTP] New client connected from %s", client_ip4_addr);
179   }
180
181   return client_fd;
182 }
183
184 int sctp_send_data(int &socket_fd, sctp_buffer_t &data)
185 {
186   int sent_len = send(socket_fd, (void*)(&(data.buffer[0])), data.len, 0);
187
188   if(sent_len == -1) {
189     perror("[SCTP] sctp_send_data");
190     exit(1);
191   }
192
193   return sent_len;
194 }
195
196 /*
197 Receive data from SCTP socket
198 Outcome of recv()
199 -1: exit the program
200 0: close the connection
201 +: new data
202 */
203 int sctp_receive_data(int &socket_fd, sctp_buffer_t &data)
204 {
205   //clear out the data before receiving
206   memset(data.buffer, 0, sizeof(data.buffer));
207   data.len = 0;
208
209   //receive data from the socket
210   int recv_len = recv(socket_fd, &(data.buffer), sizeof(data.buffer), 0);
211   if(recv_len == -1)
212   {
213     perror("[SCTP] recv");
214     exit(1);
215   }
216   else if (recv_len == 0)
217   {
218     LOG_I("[SCTP] Connection closed by remote peer");
219     if(close(socket_fd) == -1)
220     {
221       perror("[SCTP] close");
222     }
223     return -1;
224   }
225
226   data.len = recv_len;
227
228   return recv_len;
229 }