-
Notifications
You must be signed in to change notification settings - Fork 0
/
tcp-utils.cc
151 lines (129 loc) · 4.14 KB
/
tcp-utils.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
* Miscelanious TCP (and general) functions. Contains functions that
* connect active sockets, put passive sockets in listening mode, and
* read from streams.
*
* By Stefan Bruda, using the textbook as inspiration.
*/
#include "tcp-utils.h"
#include <stdio.h>
#include<poll.h>
#include<errno.h>
int connectbyport(const char* host, const char* port) {
return connectbyportint(host,(unsigned short)atoi(port));
}
int connectbyservice(const char* host, const char* service){
struct servent* sinfo = getservbyname(service,"tcp"); // service info
if (sinfo == NULL)
return err_proto;
return connectbyportint(host,(unsigned short)sinfo->s_port);
}
int connectbyportint(const char* host, const unsigned short port) {
struct hostent *hinfo; // host information
struct sockaddr_in sin; // address to connect to
int sd; // socket descriptor to be returned
const int type = SOCK_STREAM; // TCP connection
memset(&sin, 0, sizeof(sin)); // needed for correct padding... (?)
sin.sin_family = AF_INET;
// host name to IP address
hinfo = gethostbyname(host);
if (hinfo == NULL)
return err_host;
memcpy(&sin.sin_addr, hinfo->h_addr, hinfo->h_length);
sin.sin_port = (unsigned short)htons(port);
// allocate socket:
sd = socket(PF_INET, type, 0);
if ( sd < 0 )
return err_sock;
// connect socket:
int rc = connect(sd, (struct sockaddr *)&sin, sizeof(sin));
if (rc < 0) {
close(sd);
return err_connect;
}
// done!
return sd;
}
int passivesocketstr(const char* port, const int backlog) {
return passivesocket((unsigned short)atoi(port), backlog);
}
int passivesocketserv(const char* service, const int backlog) {
struct servent* sinfo = getservbyname(service,"tcp"); // service info
if (sinfo == NULL)
return err_proto;
return passivesocket((unsigned short)sinfo->s_port, backlog);
}
/*
* Helper function, contains the common code for passivesocket and
* controlsocket (which are identical except for the IP address they
* bind to).
*/
int passivesockaux(const unsigned short port, const int backlog, const unsigned long int ip_addr) {
struct sockaddr_in sin; // address to connect to
int sd; // socket description to be returned
const int type = SOCK_STREAM; // TCP connection
memset(&sin, 0, sizeof(sin)); // needed for correct padding... (?)
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(ip_addr);
sin.sin_port = (unsigned short)htons(port);
// allocate socket:
sd = socket(PF_INET, type, 0);
if ( sd < 0 )
return err_sock;
// bind socket:
if ( bind(sd, (struct sockaddr *)&sin, sizeof(sin)) < 0 ) {
close(sd);
return err_bind;
}
// socket is listening:
if ( listen(sd, backlog) < 0 ) {
close(sd);
return err_listen;
}
// done!
return sd;
}
int passivesocket(const unsigned short port, const int backlog) {
return passivesockaux(port, backlog, INADDR_ANY);
}
int controlsocket(const unsigned short port, const int backlog) {
return passivesockaux(port, backlog, INADDR_LOOPBACK);
}
int recv_nonblock(int sd, char* buf, const size_t max,int timeout) {
printf("hello buddy %d",sd);
struct pollfd pollrec;
pollrec.fd = sd;
pollrec.events = POLLIN;
printf("\ntimeout is %d\n",timeout);
int polled = poll(&pollrec,1,timeout);
if (polled == 0){
printf("\nno data received from server\n");
printf("%s",strerror(errno));
return recv_nodata;
}
if (polled == -1)
return -1;
return recv(sd,buf,max,0);
}
int readline(const int fd, char* buf, const size_t max) {
size_t i;
int begin = 1;
for (i = 0; i < max; i++) {
char tmp;
int what = read(fd,&tmp,1);
if (what == -1)
return -1;
if (begin) {
if (what == 0)
return recv_nodata;
begin = 0;
}
if (what == 0 || tmp == '\n') {
buf[i] = '\0';
return i;
}
buf[i] = tmp;
}
buf[i] = '\0';
return i;
}