PageRenderTime 22ms CodeModel.GetById 11ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/src/common/socket.c

https://github.com/TyRoXx/webserver
C | 170 lines | 142 code | 28 blank | 0 comment | 13 complexity | b2b0d2dc809b9698680010b194cb99cb MD5 | raw file
  1#include "socket.h"
  2#include <stdio.h>
  3
  4
  5#ifdef WS_UNIX
  6#include <sys/socket.h>
  7#include <arpa/inet.h>
  8#include <netinet/in.h>
  9#include <unistd.h>
 10#endif
 11
 12
 13#ifdef WS_WIN32
 14static const socket_t InvalidSocket = INVALID_SOCKET;
 15typedef int socket_size_t;
 16#else
 17static const socket_t InvalidSocket = -1;
 18typedef size_t socket_size_t;
 19#endif
 20
 21#ifdef WS_WIN32
 22static bool wsa_increment()
 23{
 24	WSADATA wsa;
 25	return WSAStartup(MAKEWORD(2, 2), &wsa) == 0;
 26}
 27
 28static void wsa_decrement()
 29{
 30	WSACleanup();
 31}
 32#endif
 33
 34bool socket_create(socket_t *socket_)
 35{
 36#ifdef WS_WIN32
 37	if (!wsa_increment())
 38	{
 39		return false;
 40	}
 41#endif
 42
 43	*socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 44	if (*socket_ == InvalidSocket)
 45	{
 46#ifdef WS_WIN32
 47		wsa_decrement();
 48#endif
 49		return false;
 50	}
 51
 52	return true;
 53}
 54
 55void socket_destroy(socket_t socket)
 56{
 57#ifdef WS_WIN32
 58	closesocket(socket);
 59	wsa_decrement();
 60#else
 61	close(socket);
 62#endif
 63}
 64
 65bool socket_bind(socket_t socket, uint16_t port)
 66{
 67	struct sockaddr_in address = {0};
 68	address.sin_family = AF_INET;
 69	address.sin_addr.s_addr = INADDR_ANY;
 70	address.sin_port = htons(port);
 71
 72	return
 73		(bind(socket, (struct sockaddr *)&address, sizeof(address)) == 0) &&
 74		(listen(socket, 10) == 0);
 75}
 76
 77bool socket_accept(socket_t socket, socket_t *accepted, socket_address_t *address)
 78{
 79	typedef
 80#ifdef WS_WIN32
 81		int
 82#else
 83		socklen_t
 84#endif
 85		address_size_t;
 86
 87	struct sockaddr_in temp_address = {0};
 88	address_size_t temp_address_size = sizeof(temp_address);
 89
 90	*accepted = accept(socket, (struct sockaddr *)&temp_address, &temp_address_size);
 91	if (*accepted == InvalidSocket)
 92	{
 93		return false;
 94	}
 95
 96#ifdef WS_WIN32
 97	if (!wsa_increment())
 98	{
 99		return false;
100	}
101#endif
102
103	if (address)
104	{
105		uint32_t const ip = temp_address.sin_addr.s_addr;
106		memcpy(address->ip.digits, &ip, sizeof(address->ip.digits));
107
108		address->port = ntohs(temp_address.sin_port);
109	}
110	return true;
111}
112
113bool socket_receive(socket_t socket, void *data, size_t size, size_t *received)
114{
115	long const rc = recv(socket, data, (socket_size_t)size, 0);
116	if (rc <= 0)
117	{
118		return false;
119	}
120
121	*received = (size_t)rc;
122	return true;
123}
124
125bool socket_send(socket_t socket, const void *data, size_t size)
126{
127	char const *remaining = data;
128	char const * const end = (remaining + size);
129
130	while (remaining < end)
131	{
132		const long rc = send(socket, remaining, (socket_size_t)(end - remaining), 0);
133		if (rc <= 0)
134		{
135			return false;
136		}
137
138		remaining += rc;
139	}
140	return true;
141}
142
143void socket_shutdown(socket_t socket)
144{
145	int const how =
146#ifdef _WIN32
147		SD_BOTH
148#else
149		SHUT_RDWR
150#endif
151		;
152
153	shutdown(socket, how);
154}
155
156
157bool ip_address_to_string(string_t *dest, ip_address_t source)
158{
159	char buffer[16];
160	sprintf(
161		buffer,
162		"%u.%u.%u.%u",
163		source.digits[0],
164		source.digits[1],
165		source.digits[2],
166		source.digits[3]
167		);
168
169	return string_assign_c_str(dest, buffer);
170}