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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
/*
* The Mana World
* Copyright 2004 The Mana World Development Team
*
* This file is part of The Mana World.
*
* The Mana World is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* The Mana World is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with The Mana World; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id$
*/
#include "network.h"
#ifndef WIN32
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#endif
/** Warning: buffers and other variables are shared,
so there can be only one connection active at a time */
int buffer_size = 65536;
char *in, *out;
int in_size, out_size;
SOCKET sock;
SOCKADDR_IN addr;
// File descriptors attached to socket
fd_set read_socket;
fd_set write_socket;
/** Increase size of written data */
void WFIFOSET(int len) {
if(out_size+len>=buffer_size)
warning("Output buffer full");
else out_size+=len;
}
/** Convert an address from int format to string */
char *iptostring(int address) {
short temp1, temp2;
static char asciiIP[16];
temp1 = LOWORD(address);
temp2 = HIWORD(address);
sprintf(asciiIP, "%i.%i.%i.%i", LOBYTE(temp1), HIBYTE(temp1), LOBYTE(temp2), HIBYTE(temp2));
return asciiIP;
}
/** Open a session with a server */
SOCKET open_session(const char* address, short port) {
#ifdef WIN32
WSADATA wsda;
#endif
struct hostent *server;
int ret;
// Init WinSock and connect the socket
#ifdef WIN32
WSAStartup(MAKEWORD(2,0), &wsda);
#endif
sock = socket(PF_INET, SOCK_STREAM, 0); // Create socket for current session
if(sock==SOCKET_ERROR)return SOCKET_ERROR;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(address);
if(addr.sin_addr.s_addr == INADDR_NONE){
server = NULL;
server = gethostbyname(address);
if(server == NULL)return SOCKET_ERROR;
memcpy(&addr.sin_addr, server->h_addr_list[0], server->h_length);
}
ret = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
if(ret == SOCKET_ERROR)return SOCKET_ERROR;
// Init buffers
in = (char *)malloc(buffer_size);
out = (char *)malloc(buffer_size);
memset(in, '\0', buffer_size);
memset(out, '\0', buffer_size);
in_size = 0;
out_size = 0;
FD_CLR(sock, &read_socket);
FD_CLR(sock, &write_socket);
return sock;
}
/** Close a session */
void close_session() {
FD_CLR(sock,&read_socket);
FD_CLR(sock,&write_socket);
closesocket(sock);
if(in!=NULL) {
free(in);
}
if(out!=NULL) {
free(out);
}
in = NULL;
out = NULL;
in_size = 0;
out_size = 0;
WSACleanup();
}
/** Send and receive data waiting in the buffers */
void flush() {
int ret = 0;
void *buf = out;
timeval time_out;
// Init the time_out struct to 0s so it won't block
time_out.tv_sec=0;
time_out.tv_usec=0;
// Clear file descriptors and set them to socket
FD_ZERO(&read_socket);
FD_ZERO(&write_socket);
FD_SET(sock, &read_socket);
FD_SET(sock, &write_socket);
// Check if socket has available data by evaluating attached file descriptors
select(FD_SETSIZE, &read_socket, &write_socket, NULL, &time_out);
// Send data if available
if(FD_ISSET(sock, &write_socket)) {
// While there wasn't a error or sent the whole data: handles partial packet send
while((ret!=SOCKET_ERROR)&&(out_size>0)) {
ret = send(sock, (char *)buf, out_size, 0);
if(ret!=SOCKET_ERROR && ret>0) {
buf = (char*)buf+ret;
out_size -= ret;
}
}
if (ret == SOCKET_ERROR) {
error("Socket Error");
#ifdef WIN32
log("Error", "Socket error: %i ", WSAGetLastError());
if (WSAGetLastError() == 10053)
log("Error", "Packet size error");
/** Probably the last packet you sent, was defined with
* wrong size: WFIFOSET(size);
*/
#else
log("Error", "socket_error", "Undefined socket error");
#endif
}
}
// Read data, if available
if(FD_ISSET(sock, &read_socket)) {
/* There's no check for partial received packets because at this level
the app doesn't know packet length, but it will done when parsing received data */
ret = recv(sock, in+in_size, RFIFOSPACE, 0);
if(ret==SOCKET_ERROR) {
#ifdef WIN32
log("Error", "Socket error: %i ", WSAGetLastError());
#else
log("Error", "socket_error", "Undefined socket error");
#endif
} else RFIFOSET(ret); // Set size of available data to read
}
}
|