-
Notifications
You must be signed in to change notification settings - Fork 91
/
Copy pathio.c
133 lines (112 loc) · 4.67 KB
/
io.c
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
/* The ssl and non-ssl portions of this file have been split out into their own separate files. */
#ifdef OPENSSL
# include "io_ssl.c"
#else
# include "io_nossl.c"
#endif
/***********************************************************************************************************************
*
* negotiate_protocol()
*
* Input: None. We leveage the global io struct.
*
* Output: 0 on success, -1 on error.
*
* Purpose: To gather agreement between the communicating parties on how big the max message size should be.
*
**********************************************************************************************************************/
int negotiate_protocol(){
unsigned short remote_data_size;
int fcntl_flags;
unsigned short tmp_ushort;
io->message_data_size = 0;
io->message_data_size--;
/* Make sure that the data_size variable will be able to hold the pagesize on this platform. */
if(pagesize > io->message_data_size){
report_error("negotiate_protocol(): pagesize bigger than max message size!");
return(-1);
}
io->message_data_size = pagesize;
/* Set the socket to non-blocking. */
if((fcntl_flags = fcntl(io->remote_fd, F_GETFL, 0)) == -1){
report_error("negotiate_protocol(): fcntl(%d, F_GETFL, 0): %s", io->remote_fd, strerror(errno));
return(-1);
}
fcntl_flags |= O_NONBLOCK;
if(fcntl(io->remote_fd, F_SETFL, fcntl_flags) == -1){
report_error("negotiate_protocol(): fcntl(%d, F_SETFL, %d): %s", io->remote_fd, fcntl_flags, strerror(errno));
return(-1);
}
/* Send and receive protocol major and minor numbers. */
// This information isn't used outside of reporting yet, but should be useful someday.
tmp_ushort = htons(io->control_proto_major);
if(io->remote_write(&tmp_ushort, sizeof(tmp_ushort)) == -1){
report_error("negotiate_protocol(): io->remote_write(%lx, %d): %s", \
(unsigned long) &tmp_ushort, (int) sizeof(tmp_ushort), strerror(errno));
return(-1);
}
tmp_ushort = htons(io->control_proto_minor);
if(io->remote_write(&tmp_ushort, sizeof(tmp_ushort)) == -1){
report_error("negotiate_protocol(): io->remote_write(%lx, %d): %s", \
(unsigned long) &tmp_ushort, (int) sizeof(tmp_ushort), strerror(errno));
return(-1);
}
if(io->remote_read(&tmp_ushort, sizeof(tmp_ushort)) == -1){
report_error("negotiate_protocol(): io->remote_read(%lx, %d): %s", \
(unsigned long) &tmp_ushort, (int) sizeof(tmp_ushort), strerror(errno));
return(-1);
}
io->target_proto_major = ntohs(tmp_ushort);
if(io->remote_read(&tmp_ushort, sizeof(tmp_ushort)) == -1){
report_error("negotiate_protocol(): io->remote_read(%lx, %d): %s", \
(unsigned long) &tmp_ushort, (int) sizeof(tmp_ushort), strerror(errno));
return(-1);
}
io->target_proto_minor = ntohs(tmp_ushort);
if(io->control_proto_major != io->target_proto_major || io->control_proto_minor != io->target_proto_minor){
report_error("Protocol mismatch: control v%d.%d != target v%d.%d: Continuing...", \
io->control_proto_major, io->control_proto_minor, io->target_proto_major, io->target_proto_minor);
}
/* Send our desired message size. */
tmp_ushort = htons(io->message_data_size);
if(io->remote_write(&tmp_ushort, sizeof(tmp_ushort)) == -1){
report_error("negotiate_protocol(): io->remote_write(%lx, %d): %s", \
(unsigned long) &tmp_ushort, (int) sizeof(tmp_ushort), strerror(errno));
return(-1);
}
/* Receive their desired message size. */
if(io->remote_read(&tmp_ushort, sizeof(tmp_ushort)) == -1){
report_error("negotiate_protocol(): io->remote_read(%lx, %d): %s", \
(unsigned long) &tmp_ushort, (int) sizeof(tmp_ushort), strerror(errno));
return(-1);
}
remote_data_size = ntohs(tmp_ushort);
/* Make sure it isn't smaller than our totally reasonable minimum. */
if(remote_data_size < MINIMUM_MESSAGE_SIZE){
report_error("negotiate_protocol(): Can't agree on a message size!");
return(-1);
}
/* Set the message size to the smaller of the two, and malloc the space. */
io->message_data_size = io->message_data_size < remote_data_size ? io->message_data_size : remote_data_size;
if((message->data = (char *) malloc(io->message_data_size)) == NULL){
report_error("negotiate_protocol(): malloc(%d): %s", io->message_data_size, strerror(errno));
return(-1);
}
return(0);
}
/***********************************************************************************************************************
*
* seppuku()
*
* Input: The signal being handled. (SIGALRM)
* Output: None.
*
* Purpose: To catch SIGALRM and exit quietly. (切腹)
*
**********************************************************************************************************************/
void seppuku(int signal){
if(verbose){
report_error("sepuku(): Timeout reached. exiting.\n");
}
exit(-signal);
}