blob: dad446ce5a1a1c6a2341d12dd67a184f7c088200 [file] [log] [blame]
Jeff Thompson7850d782013-07-14 17:59:14 -07001/**
2 * @author: Jeff Thompson
3 * See COPYING for copyright and distribution information.
4 */
5
6#include "TcpTransport.h"
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <unistd.h>
11#include <errno.h>
12#include <string.h>
13#include <netdb.h>
14#include <sys/types.h>
15#include <netinet/in.h>
16#include <sys/socket.h>
17
18#include <arpa/inet.h>
19
20// get sockaddr, IPv4 or IPv6:
21static inline void *get_in_addr(struct sockaddr *sa)
22{
23 if (sa->sa_family == AF_INET)
24 return &(((struct sockaddr_in*)sa)->sin_addr);
25
26 return &(((struct sockaddr_in6*)sa)->sin6_addr);
27}
28
Jeff Thompson0d567da2013-07-14 22:10:21 -070029ndn_Error ndn_TcpTransport_connect(struct ndn_TcpTransport *self, char *host, unsigned short port)
Jeff Thompson7850d782013-07-14 17:59:14 -070030{
Jeff Thompson0d567da2013-07-14 22:10:21 -070031 if (self->socketDescriptor >= 0) {
32 close(self->socketDescriptor);
33 self->socketDescriptor = -1;
34 }
Jeff Thompson7850d782013-07-14 17:59:14 -070035
Jeff Thompson0d567da2013-07-14 22:10:21 -070036 struct addrinfo hints;
Jeff Thompson7850d782013-07-14 17:59:14 -070037 memset(&hints, 0, sizeof hints);
38 hints.ai_family = AF_UNSPEC;
39 hints.ai_socktype = SOCK_STREAM;
40
Jeff Thompson0d567da2013-07-14 22:10:21 -070041 char portString[10];
42 sprintf(portString, "%d", port);
43
44 struct addrinfo *serverInfo;
45 if (getaddrinfo(host, portString, &hints, &serverInfo) != 0)
46 return NDN_ERROR_TcpTransport_error_in_getaddrinfo;
Jeff Thompson7850d782013-07-14 17:59:14 -070047
48 // loop through all the results and connect to the first we can
49 struct addrinfo *p;
Jeff Thompson0d567da2013-07-14 22:10:21 -070050 int socketDescriptor;
Jeff Thompson7850d782013-07-14 17:59:14 -070051 for(p = serverInfo; p != NULL; p = p->ai_next) {
52 if ((socketDescriptor = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
53 continue;
54
55 if (connect(socketDescriptor, p->ai_addr, p->ai_addrlen) == -1) {
56 close(socketDescriptor);
57 continue;
58 }
59
60 break;
61 }
62
Jeff Thompson0d567da2013-07-14 22:10:21 -070063 if (p == NULL) {
64 freeaddrinfo(serverInfo);
65 return NDN_ERROR_TcpTransport_cannot_connect_to_socket;
66 }
Jeff Thompson7850d782013-07-14 17:59:14 -070067
Jeff Thompson0d567da2013-07-14 22:10:21 -070068 freeaddrinfo(serverInfo);
69 self->socketDescriptor = socketDescriptor;
Jeff Thompson7850d782013-07-14 17:59:14 -070070
Jeff Thompson0d567da2013-07-14 22:10:21 -070071 return 0;
72}
73
74ndn_Error ndn_TcpTransport_send(struct ndn_TcpTransport *self, unsigned char *data, unsigned int dataLength)
75{
76 if (self->socketDescriptor < 0)
77 return NDN_ERROR_TcpTransport_socket_is_not_open;
78
Jeff Thompson7850d782013-07-14 17:59:14 -070079 int nBytes;
80 while (1) {
Jeff Thompson0d567da2013-07-14 22:10:21 -070081 if ((nBytes = send(self->socketDescriptor, data, dataLength, 0)) < 0)
82 return NDN_ERROR_TcpTransport_error_in_send;
Jeff Thompson7850d782013-07-14 17:59:14 -070083 if (nBytes >= dataLength)
84 break;
85
Jeff Thompson0d567da2013-07-14 22:10:21 -070086 // Send more.
Jeff Thompson7850d782013-07-14 17:59:14 -070087 dataLength -= nBytes;
88 }
Jeff Thompson0d567da2013-07-14 22:10:21 -070089
90 return 0;
91}
92
93ndn_Error ndn_TcpTransport_receive
94(struct ndn_TcpTransport *self, unsigned char *buffer, unsigned int bufferLength, unsigned int *nBytesOut)
95{
96 if (self->socketDescriptor < 0)
97 return NDN_ERROR_TcpTransport_socket_is_not_open;
98
99 int nBytes;
100 if ((nBytes = recv(self->socketDescriptor, buffer, bufferLength, 0)) == -1)
101 return NDN_ERROR_TcpTransport_error_in_recv;
102
103 *nBytesOut = (unsigned int)nBytes;
Jeff Thompson7850d782013-07-14 17:59:14 -0700104
Jeff Thompson0d567da2013-07-14 22:10:21 -0700105 return 0;
Jeff Thompson7850d782013-07-14 17:59:14 -0700106}