Harry Tran | 1f1098a | 2020-03-10 10:40:10 -0400 | [diff] [blame] | 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); |
Ron Shacham | a9733db | 2020-09-14 12:05:31 -0400 | [diff] [blame^] | 209 | fprintf(stderr, "client fd is %d\n", client_fd); |
Harry Tran | 1f1098a | 2020-03-10 10:40:10 -0400 | [diff] [blame] | 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 | { |
Ron Shacham | a9733db | 2020-09-14 12:05:31 -0400 | [diff] [blame^] | 235 | fprintf(stderr,"in sctp send data func\n"); |
| 236 | fprintf(stderr,"data.len is %d", data.len); |
Harry Tran | 1f1098a | 2020-03-10 10:40:10 -0400 | [diff] [blame] | 237 | int sent_len = send(socket_fd, (void*)(&(data.buffer[0])), data.len, 0); |
Ron Shacham | a9733db | 2020-09-14 12:05:31 -0400 | [diff] [blame^] | 238 | fprintf(stderr,"after getting sent_len\n"); |
Harry Tran | 1f1098a | 2020-03-10 10:40:10 -0400 | [diff] [blame] | 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 | { |
Ron Shacham | a9733db | 2020-09-14 12:05:31 -0400 | [diff] [blame^] | 250 | /* |
Harry Tran | 1f1098a | 2020-03-10 10:40:10 -0400 | [diff] [blame] | 251 | int sent_len = sctp_sendmsg(socket_fd, (void*)(&(data.buffer[0])), data.len, |
| 252 | NULL, 0, (uint32_t) X2AP_PPID, 0, 0, 0, 0); |
| 253 | |
| 254 | if(sent_len == -1) { |
| 255 | perror("[SCTP] sctp_send_data"); |
| 256 | exit(1); |
| 257 | } |
Ron Shacham | a9733db | 2020-09-14 12:05:31 -0400 | [diff] [blame^] | 258 | */ |
| 259 | return 1; |
Harry Tran | 1f1098a | 2020-03-10 10:40:10 -0400 | [diff] [blame] | 260 | } |
| 261 | |
| 262 | /* |
| 263 | Receive data from SCTP socket |
| 264 | Outcome of recv() |
| 265 | -1: exit the program |
| 266 | 0: close the connection |
| 267 | +: new data |
| 268 | */ |
| 269 | int sctp_receive_data(int &socket_fd, sctp_buffer_t &data) |
| 270 | { |
| 271 | //clear out the data before receiving |
Ron Shacham | a9733db | 2020-09-14 12:05:31 -0400 | [diff] [blame^] | 272 | fprintf(stderr, "receive data1\n"); |
Harry Tran | 1f1098a | 2020-03-10 10:40:10 -0400 | [diff] [blame] | 273 | memset(data.buffer, 0, sizeof(data.buffer)); |
Ron Shacham | a9733db | 2020-09-14 12:05:31 -0400 | [diff] [blame^] | 274 | fprintf(stderr, "receive data2\n"); |
Harry Tran | 1f1098a | 2020-03-10 10:40:10 -0400 | [diff] [blame] | 275 | data.len = 0; |
| 276 | |
| 277 | //receive data from the socket |
| 278 | int recv_len = recv(socket_fd, &(data.buffer), sizeof(data.buffer), 0); |
Ron Shacham | a9733db | 2020-09-14 12:05:31 -0400 | [diff] [blame^] | 279 | fprintf(stderr, "receive data3\n"); |
| 280 | |
Harry Tran | 1f1098a | 2020-03-10 10:40:10 -0400 | [diff] [blame] | 281 | if(recv_len == -1) |
| 282 | { |
| 283 | perror("[SCTP] recv"); |
| 284 | exit(1); |
| 285 | } |
| 286 | else if (recv_len == 0) |
| 287 | { |
| 288 | LOG_I("[SCTP] Connection closed by remote peer"); |
| 289 | if(close(socket_fd) == -1) |
| 290 | { |
| 291 | perror("[SCTP] close"); |
| 292 | } |
| 293 | return -1; |
| 294 | } |
| 295 | |
| 296 | data.len = recv_len; |
| 297 | |
| 298 | return recv_len; |
| 299 | } |