socket.c
3.95 KB
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
181
182
183
184
/*
* some basic berkley socket stuff....far from beeing complete
*/
#define USE_STRUCT_SCOT_SOCKET
#include <string.h>
#include <scot/exception.h>
#include <scot/memory.h>
#include <scot/stream.h>
#include <scot/socket.h>
#include <scot/socket_in.h>
#ifndef WIN32
# include <scot/socket_un.h>
#endif /* WIN32 */
#include <scot_common.h>
#define SCOT_SOCKET_NEW_FAIL 0
#define SCOT_SOCKET_LISTEN_FAIL 1
#define SCOT_SOCKET_ACCEPT_FAIL 2
#define SCOT_SOCKET_CONNECT_FAIL 3
#define SCOT_SOCKET_NO_VALID_HOST 4
#define SCOT_SOCKET_AF_NOT_IMPLEMENTED 5
const char * scot_socket_errmsg[] =
{
"[SOCKET]failed to create new socket",
"[SOCKET]failed to listen on port specified with socket",
"[SOCKET]failed to accept connections on socket",
"[SOCKET]failed to connect with socket",
"[SOCKET]invalid hostname",
"[SOCKET]address family not implemented"
};
const char * scot_socket_wrnmsg[] =
{
"[SOCKET]there was already an existent socket file.\n"
" i removed that file to let the new instance of the program\n"
" work, but notice that there might be another instance of this\n"
" program running, that is unusable hence now."
};
void
scot_socket_init (uint16_t major, uint16_t minor)
{
#ifdef WIN32
WORD version = MAKEWORD (major,minor);
WSADATA wsa_data;
WSAStartup (version, &wsa_data);
#endif
}
void
scot_socket_fini (void)
{
int a;
#ifdef WIN32
WSACleanup ();
#endif
}
/*
* actualy i found no good reason to bind a socken if one
* dont wants to listen to it too. If i find one i will change this.
*/
void
scot_socket_listen (const struct scot_socket* s)
{
excenv_t *ee;
TRY
{
if (bind (s->socket.handle.sock, s->sa, s->addr_len) == -1)
THROW (EXC (EXC_ERROR, SCOT_ERRNO, strerror (SCOT_ERRNO)));
if (listen (s->socket.handle.sock, SCOT_SOCKET_BACKLOG) == -1)
THROW (EXC (EXC_ERROR, SCOT_ERRNO, strerror (SCOT_ERRNO)));
}
CATCH (ee)
{
/*
* if we got an Address already in use error on a unix domain
* socket it is most likely because there is a stale socket file
* around. Then we can try to unlink it and retry the listen.
*/
exception_t * e;
while (e = retrive_exception (ee))
{
#ifndef WIN32
if (exc_errnum_get (e) == EADDRINUSE && s->sa->sa_family == AF_UNIX)
{
if (unlink (((struct sockaddr_un *) s->sa)->sun_path) == -1)
{
THROW (e);
THROW (EXC (EXC_ERROR,
SCOT_SOCKET_LISTEN_FAIL,
scot_socket_errmsg [SCOT_SOCKET_LISTEN_FAIL]));
}
else
{
THROW (EXC (EXC_WARNING,
SCOT_SOCKET_UN_FILE_EXISTS,
scot_socket_wrnmsg [SCOT_SOCKET_UN_FILE_EXISTS]));
free_exception (e);
scot_socket_listen (s);
}
}
else
#endif
{
THROW (e);
THROW (EXC (EXC_ERROR,
SCOT_SOCKET_LISTEN_FAIL,
scot_socket_errmsg [SCOT_SOCKET_LISTEN_FAIL]));
}
}
free_catched (ee);
}
}
struct scot_socket *
scot_socket_accept (const struct scot_socket* s)
{
switch (s->sa->sa_family)
{
#ifndef WIN32
case AF_UNIX: return scot_socket_un_accept (s);
#endif /* WIN32 */
case AF_INET: return scot_socket_in_accept (s);
}
}
void
scot_socket_connect (const struct scot_socket * s, const char * adr)
{
excenv_t * ee;
TRY
{
switch (s->sa->sa_family)
{
#ifndef WIN32
case AF_UNIX:
scot_socket_un_prep_con (s, adr); break;
#endif /* WIN32 */
case AF_INET:
scot_socket_in_prep_con (s, adr); break;
default:
THROW (EXC (EXC_ERROR,
SCOT_SOCKET_AF_NOT_IMPLEMENTED,
scot_socket_errmsg [SCOT_SOCKET_AF_NOT_IMPLEMENTED]));
}
if ((connect (s->socket.handle.sock, s->sa, s->addr_len)) == -1)
THROW (EXC (EXC_ERROR, SCOT_ERRNO, strerror (SCOT_ERRNO)));
}
CATCH (ee)
{
forward_all_exceptions (ee);
THROW (EXC (EXC_ERROR,
SCOT_SOCKET_CONNECT_FAIL,
scot_socket_errmsg [SCOT_SOCKET_CONNECT_FAIL]));
}
}
void
scot_socket_free (struct scot_socket * s)
{
if (s)
{
if (s->sa)
SCOT_MEM_FREE (s->sa);
SCOT_SOCK_CLOSE (s->socket.handle.sock);
SCOT_MEM_FREE (s);
}
}