blob: 53987b076f1bd68cc0d06d3bb7f7b1a431ebaaf7 [file] [log] [blame]
Jeff Thompson7790c682013-07-17 17:22:12 -07001/**
Jeff Thompson7687dc02013-09-13 11:54:07 -07002 * Copyright (C) 2013 Regents of the University of California.
3 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
Jeff Thompson7790c682013-07-17 17:22:12 -07004 * See COPYING for copyright and distribution information.
5 */
6
Jeff Thompson53412192013-08-06 13:35:50 -07007#include "socket-transport.h"
Jeff Thompson7790c682013-07-17 17:22:12 -07008
9#include <stdio.h>
10#include <stdlib.h>
11#include <unistd.h>
12#include <netdb.h>
13#include <sys/types.h>
14#include <netinet/in.h>
15#include <sys/socket.h>
16#include <arpa/inet.h>
Jeff Thompson432c8be2013-08-09 16:16:08 -070017#include <poll.h>
Jeff Thompson7790c682013-07-17 17:22:12 -070018#include "../util/ndn_memory.h"
19
Jeff Thompson0aa754a2013-07-17 17:42:28 -070020ndn_Error ndn_SocketTransport_connect(struct ndn_SocketTransport *self, ndn_SocketType socketType, char *host, unsigned short port)
Jeff Thompson7790c682013-07-17 17:22:12 -070021{
22 if (self->socketDescriptor >= 0) {
23 close(self->socketDescriptor);
24 self->socketDescriptor = -1;
25 }
26
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070027 struct addrinfo hints;
28 ndn_memset((unsigned char *)&hints, 0, sizeof(hints));
29 hints.ai_family = AF_UNSPEC;
Jeff Thompson0aa754a2013-07-17 17:42:28 -070030 if (socketType == SOCKET_TCP)
31 hints.ai_socktype = SOCK_STREAM;
32 else if (socketType == SOCKET_UDP)
33 hints.ai_socktype = SOCK_DGRAM;
34 else
35 return NDN_ERROR_unrecognized_ndn_SocketTransport;
Jeff Thompson7790c682013-07-17 17:22:12 -070036
37 char portString[10];
38 sprintf(portString, "%d", port);
39
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070040 struct addrinfo *serverInfo;
41 if (getaddrinfo(host, portString, &hints, &serverInfo) != 0)
42 return NDN_ERROR_SocketTransport_error_in_getaddrinfo;
Jeff Thompson7790c682013-07-17 17:22:12 -070043
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070044 // loop through all the results and connect to the first we can
45 struct addrinfo *p;
Jeff Thompson7790c682013-07-17 17:22:12 -070046 int socketDescriptor;
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070047 for(p = serverInfo; p != NULL; p = p->ai_next) {
48 if ((socketDescriptor = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
49 continue;
Jeff Thompson7790c682013-07-17 17:22:12 -070050
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070051 if (connect(socketDescriptor, p->ai_addr, p->ai_addrlen) == -1) {
52 close(socketDescriptor);
53 continue;
54 }
Jeff Thompson7790c682013-07-17 17:22:12 -070055
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070056 break;
Jeff Thompson7790c682013-07-17 17:22:12 -070057 }
58
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070059 if (p == NULL) {
60 freeaddrinfo(serverInfo);
61 return NDN_ERROR_SocketTransport_cannot_connect_to_socket;
62 }
63
64 freeaddrinfo(serverInfo);
Jeff Thompson7790c682013-07-17 17:22:12 -070065 self->socketDescriptor = socketDescriptor;
66
Jeff Thompsonadaf9232013-08-08 14:30:29 -070067 return NDN_ERROR_success;
Jeff Thompson7790c682013-07-17 17:22:12 -070068}
69
Jeff Thompson0aa754a2013-07-17 17:42:28 -070070ndn_Error ndn_SocketTransport_send(struct ndn_SocketTransport *self, unsigned char *data, unsigned int dataLength)
Jeff Thompson7790c682013-07-17 17:22:12 -070071{
72 if (self->socketDescriptor < 0)
Jeff Thompson0aa754a2013-07-17 17:42:28 -070073 return NDN_ERROR_SocketTransport_socket_is_not_open;
Jeff Thompson7790c682013-07-17 17:22:12 -070074
75 int nBytes;
76 while (1) {
77 if ((nBytes = send(self->socketDescriptor, data, dataLength, 0)) < 0)
Jeff Thompson0aa754a2013-07-17 17:42:28 -070078 return NDN_ERROR_SocketTransport_error_in_send;
Jeff Thompson7790c682013-07-17 17:22:12 -070079 if (nBytes >= dataLength)
80 break;
81
82 // Send more.
83 dataLength -= nBytes;
84 }
85
Jeff Thompsonadaf9232013-08-08 14:30:29 -070086 return NDN_ERROR_success;
Jeff Thompson7790c682013-07-17 17:22:12 -070087}
88
Jeff Thompson432c8be2013-08-09 16:16:08 -070089ndn_Error ndn_SocketTransport_receiveIsReady(struct ndn_SocketTransport *self, int *receiveIsReady)
90{
91 // Default to not ready.
92 *receiveIsReady = 0;
93
94 if (self->socketDescriptor < 0)
95 // The socket is not open. Just silently return.
96 return NDN_ERROR_success;
97
98 struct pollfd pollInfo[1];
99 pollInfo[0].fd = self->socketDescriptor;
100 pollInfo[0].events = POLLIN;
101
Jeff Thompsonc7e07442013-08-19 15:25:43 -0700102 int pollResult = poll(pollInfo, 1, 0);
Jeff Thompson432c8be2013-08-09 16:16:08 -0700103
104 if (pollResult < 0)
105 return NDN_ERROR_SocketTransport_error_in_poll;
106 else if (pollResult == 0)
107 // Timeout, so no data ready.
108 return NDN_ERROR_success;
109 else {
110 if (pollInfo[0].revents & POLLIN)
111 *receiveIsReady = 1;
112 }
113
114 return NDN_ERROR_success;
115}
116
Jeff Thompson0aa754a2013-07-17 17:42:28 -0700117ndn_Error ndn_SocketTransport_receive
Jeff Thompson432c8be2013-08-09 16:16:08 -0700118 (struct ndn_SocketTransport *self, unsigned char *buffer, unsigned int bufferLength, unsigned int *nBytesOut)
Jeff Thompson7790c682013-07-17 17:22:12 -0700119{
120 if (self->socketDescriptor < 0)
Jeff Thompson0aa754a2013-07-17 17:42:28 -0700121 return NDN_ERROR_SocketTransport_socket_is_not_open;
Jeff Thompson7790c682013-07-17 17:22:12 -0700122
123 int nBytes;
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700124 if ((nBytes = recv(self->socketDescriptor, buffer, bufferLength, 0)) == -1)
Jeff Thompson0aa754a2013-07-17 17:42:28 -0700125 return NDN_ERROR_SocketTransport_error_in_recv;
Jeff Thompson7790c682013-07-17 17:22:12 -0700126
127 *nBytesOut = (unsigned int)nBytes;
128
Jeff Thompson2d27e2f2013-08-09 12:55:00 -0700129 return NDN_ERROR_success;
Jeff Thompson7790c682013-07-17 17:22:12 -0700130}
Jeff Thompson57963882013-08-05 16:01:25 -0700131
132ndn_Error ndn_SocketTransport_close(struct ndn_SocketTransport *self)
133{
134 if (self->socketDescriptor < 0)
135 // Already closed. Do nothing.
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700136 return NDN_ERROR_success;
Jeff Thompson57963882013-08-05 16:01:25 -0700137
138 if (close(self->socketDescriptor) != 0)
139 return NDN_ERROR_SocketTransport_error_in_close;
140
141 self->socketDescriptor = -1;
142
Jeff Thompsonadaf9232013-08-08 14:30:29 -0700143 return NDN_ERROR_success;
Jeff Thompson57963882013-08-05 16:01:25 -0700144}