blob: 2a537dbca8664f40fbd7ff0d928822915517d191 [file] [log] [blame]
Jeff Thompson7790c682013-07-17 17:22:12 -07001/**
2 * @author: Jeff Thompson
3 * See COPYING for copyright and distribution information.
4 */
5
Jeff Thompson53412192013-08-06 13:35:50 -07006#include "socket-transport.h"
Jeff Thompson7790c682013-07-17 17:22:12 -07007
8#include <stdio.h>
9#include <stdlib.h>
10#include <unistd.h>
11#include <netdb.h>
12#include <sys/types.h>
13#include <netinet/in.h>
14#include <sys/socket.h>
15#include <arpa/inet.h>
Jeff Thompson432c8be2013-08-09 16:16:08 -070016#include <poll.h>
Jeff Thompson7790c682013-07-17 17:22:12 -070017#include "../util/ndn_memory.h"
18
Jeff Thompson0aa754a2013-07-17 17:42:28 -070019ndn_Error ndn_SocketTransport_connect(struct ndn_SocketTransport *self, ndn_SocketType socketType, char *host, unsigned short port)
Jeff Thompson7790c682013-07-17 17:22:12 -070020{
21 if (self->socketDescriptor >= 0) {
22 close(self->socketDescriptor);
23 self->socketDescriptor = -1;
24 }
25
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070026 struct addrinfo hints;
27 ndn_memset((unsigned char *)&hints, 0, sizeof(hints));
28 hints.ai_family = AF_UNSPEC;
Jeff Thompson0aa754a2013-07-17 17:42:28 -070029 if (socketType == SOCKET_TCP)
30 hints.ai_socktype = SOCK_STREAM;
31 else if (socketType == SOCKET_UDP)
32 hints.ai_socktype = SOCK_DGRAM;
33 else
34 return NDN_ERROR_unrecognized_ndn_SocketTransport;
Jeff Thompson7790c682013-07-17 17:22:12 -070035
36 char portString[10];
37 sprintf(portString, "%d", port);
38
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070039 struct addrinfo *serverInfo;
40 if (getaddrinfo(host, portString, &hints, &serverInfo) != 0)
41 return NDN_ERROR_SocketTransport_error_in_getaddrinfo;
Jeff Thompson7790c682013-07-17 17:22:12 -070042
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070043 // loop through all the results and connect to the first we can
44 struct addrinfo *p;
Jeff Thompson7790c682013-07-17 17:22:12 -070045 int socketDescriptor;
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070046 for(p = serverInfo; p != NULL; p = p->ai_next) {
47 if ((socketDescriptor = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
48 continue;
Jeff Thompson7790c682013-07-17 17:22:12 -070049
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070050 if (connect(socketDescriptor, p->ai_addr, p->ai_addrlen) == -1) {
51 close(socketDescriptor);
52 continue;
53 }
Jeff Thompson7790c682013-07-17 17:22:12 -070054
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070055 break;
Jeff Thompson7790c682013-07-17 17:22:12 -070056 }
57
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070058 if (p == NULL) {
59 freeaddrinfo(serverInfo);
60 return NDN_ERROR_SocketTransport_cannot_connect_to_socket;
61 }
62
63 freeaddrinfo(serverInfo);
Jeff Thompson7790c682013-07-17 17:22:12 -070064 self->socketDescriptor = socketDescriptor;
65
Jeff Thompsonadaf9232013-08-08 14:30:29 -070066 return NDN_ERROR_success;
Jeff Thompson7790c682013-07-17 17:22:12 -070067}
68
Jeff Thompson0aa754a2013-07-17 17:42:28 -070069ndn_Error ndn_SocketTransport_send(struct ndn_SocketTransport *self, unsigned char *data, unsigned int dataLength)
Jeff Thompson7790c682013-07-17 17:22:12 -070070{
71 if (self->socketDescriptor < 0)
Jeff Thompson0aa754a2013-07-17 17:42:28 -070072 return NDN_ERROR_SocketTransport_socket_is_not_open;
Jeff Thompson7790c682013-07-17 17:22:12 -070073
74 int nBytes;
75 while (1) {
76 if ((nBytes = send(self->socketDescriptor, data, dataLength, 0)) < 0)
Jeff Thompson0aa754a2013-07-17 17:42:28 -070077 return NDN_ERROR_SocketTransport_error_in_send;
Jeff Thompson7790c682013-07-17 17:22:12 -070078 if (nBytes >= dataLength)
79 break;
80
81 // Send more.
82 dataLength -= nBytes;
83 }
84
Jeff Thompsonadaf9232013-08-08 14:30:29 -070085 return NDN_ERROR_success;
Jeff Thompson7790c682013-07-17 17:22:12 -070086}
87
Jeff Thompson432c8be2013-08-09 16:16:08 -070088ndn_Error ndn_SocketTransport_receiveIsReady(struct ndn_SocketTransport *self, int *receiveIsReady)
89{
90 // Default to not ready.
91 *receiveIsReady = 0;
92
93 if (self->socketDescriptor < 0)
94 // The socket is not open. Just silently return.
95 return NDN_ERROR_success;
96
97 struct pollfd pollInfo[1];
98 pollInfo[0].fd = self->socketDescriptor;
99 pollInfo[0].events = POLLIN;
100
101 int pollResult = poll(pollInfo, 1, 200);
102
103 if (pollResult < 0)
104 return NDN_ERROR_SocketTransport_error_in_poll;
105 else if (pollResult == 0)
106 // Timeout, so no data ready.
107 return NDN_ERROR_success;
108 else {
109 if (pollInfo[0].revents & POLLIN)
110 *receiveIsReady = 1;
111 }
112
113 return NDN_ERROR_success;
114}
115
Jeff Thompson0aa754a2013-07-17 17:42:28 -0700116ndn_Error ndn_SocketTransport_receive
Jeff Thompson432c8be2013-08-09 16:16:08 -0700117 (struct ndn_SocketTransport *self, unsigned char *buffer, unsigned int bufferLength, unsigned int *nBytesOut)
Jeff Thompson7790c682013-07-17 17:22:12 -0700118{
119 if (self->socketDescriptor < 0)
Jeff Thompson0aa754a2013-07-17 17:42:28 -0700120 return NDN_ERROR_SocketTransport_socket_is_not_open;
Jeff Thompson7790c682013-07-17 17:22:12 -0700121
122 int nBytes;
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700123 if ((nBytes = recv(self->socketDescriptor, buffer, bufferLength, 0)) == -1)
Jeff Thompson0aa754a2013-07-17 17:42:28 -0700124 return NDN_ERROR_SocketTransport_error_in_recv;
Jeff Thompson7790c682013-07-17 17:22:12 -0700125
126 *nBytesOut = (unsigned int)nBytes;
127
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700128 return NDN_ERROR_success;
Jeff Thompson7790c682013-07-17 17:22:12 -0700129}
Jeff Thompson57963882013-08-05 16:01:25 -0700130
131ndn_Error ndn_SocketTransport_close(struct ndn_SocketTransport *self)
132{
133 if (self->socketDescriptor < 0)
134 // Already closed. Do nothing.
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700135 return NDN_ERROR_success;
Jeff Thompson57963882013-08-05 16:01:25 -0700136
137 if (close(self->socketDescriptor) != 0)
138 return NDN_ERROR_SocketTransport_error_in_close;
139
140 self->socketDescriptor = -1;
141
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700142 return NDN_ERROR_success;
Jeff Thompson57963882013-08-05 16:01:25 -0700143}