port.c 9.73 KB
Newer Older
Simon Morlat's avatar
Simon Morlat committed
1 2 3 4 5 6
/*
	belle-sip - SIP (RFC3261) library.
    Copyright (C) 2010  Belledonne Communications SARL

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation, either version 2 of the License, or
Simon Morlat's avatar
Simon Morlat committed
8 9 10 11 12 13 14 15 16 17 18 19 20
    (at your option) any later version.

    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "belle_sip_internal.h"

21
#ifdef _WIN32
Simon Morlat's avatar
Simon Morlat committed
22

23
#include <process.h>
24
#include <time.h>
25

26 27
#ifdef HAVE_COMPILER_TLS
static __declspec(thread) const void *current_thread_data = NULL;
28 29
#endif

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
static int sockets_initd=0;

int belle_sip_init_sockets(void){
	if (sockets_initd==0){
		WSADATA data;
		int err = WSAStartup(MAKEWORD(2,2), &data);
		if (err != 0) {
			belle_sip_error("WSAStartup failed with error: %d\n", err);
			return -1;
		}
	}
	sockets_initd++;
	return 0;
}

void belle_sip_uninit_sockets(void){
	sockets_initd--;
	if (sockets_initd==0) WSACleanup();
}

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
typedef struct thread_param {
	void * (*func)(void *);
	void * arg;
} thread_param_t;

static unsigned WINAPI thread_starter(void *data) {
	thread_param_t *params = (thread_param_t*)data;
	void *ret = params->func(params->arg);
	belle_sip_free(data);
	return (DWORD)ret;
}

int belle_sip_thread_create(belle_sip_thread_t *thread, void *attr, void * (*func)(void *), void *data) {
	thread_param_t *params = belle_sip_new(thread_param_t);
	params->func = func;
	params->arg = data;
	*thread = (HANDLE)_beginthreadex(NULL, 0, thread_starter, params, 0, NULL);
	return 0;
}

int belle_sip_thread_join(belle_sip_thread_t thread, void **unused) {
	if (thread != NULL) {
72
		WaitForSingleObjectEx(thread, INFINITE, FALSE);
73 74 75 76 77 78
		CloseHandle(thread);
	}
	return 0;
}

int belle_sip_mutex_init(belle_sip_mutex_t *mutex, void *attr) {
79
#ifdef BELLE_SIP_WINDOWS_DESKTOP
80 81 82 83 84 85 86 87
	*mutex = CreateMutex(NULL, FALSE, NULL);
#else
	InitializeSRWLock(mutex);
#endif
	return 0;
}

int belle_sip_mutex_lock(belle_sip_mutex_t * hMutex) {
88
#ifdef BELLE_SIP_WINDOWS_DESKTOP
89 90 91 92 93 94 95 96
	WaitForSingleObject(*hMutex, INFINITE);
#else
	AcquireSRWLockExclusive(hMutex);
#endif
	return 0;
}

int belle_sip_mutex_unlock(belle_sip_mutex_t * hMutex) {
97
#ifdef BELLE_SIP_WINDOWS_DESKTOP
98 99 100 101 102 103 104 105
	ReleaseMutex(*hMutex);
#else
	ReleaseSRWLockExclusive(hMutex);
#endif
	return 0;
}

int belle_sip_mutex_destroy(belle_sip_mutex_t * hMutex) {
106
#ifdef BELLE_SIP_WINDOWS_DESKTOP
107 108 109 110 111 112
	CloseHandle(*hMutex);
#endif
	return 0;
}

int belle_sip_socket_set_nonblocking(belle_sip_socket_t sock)
113 114 115 116 117
{
	unsigned long nonBlock = 1;
	return ioctlsocket(sock, FIONBIO , &nonBlock);
}

Simon Morlat's avatar
Simon Morlat committed
118 119 120 121 122
int belle_sip_socket_set_dscp(belle_sip_socket_t sock, int ai_family, int dscp){
	belle_sip_warning("belle_sip_socket_set_dscp(): not implemented.");
	return -1;
}

123 124 125 126 127
const char *belle_sip_get_socket_error_string(){
	return belle_sip_get_socket_error_string_from_code(WSAGetLastError());
}

const char *belle_sip_get_socket_error_string_from_code(int code){
128
	static CHAR msgBuf[256];
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
#ifdef _UNICODE
	static WCHAR wMsgBuf[256];
	int ret;
	FormatMessageW(
			FORMAT_MESSAGE_FROM_SYSTEM |
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			code,
			0, // Default language
			(LPWSTR) &wMsgBuf,
			sizeof(wMsgBuf),
			NULL);
	ret = wcstombs(msgBuf, wMsgBuf, sizeof(msgBuf));
	if (ret == sizeof(msgBuf)) msgBuf[sizeof(msgBuf) - 1] = '\0';
#else
	FormatMessageA(
145 146 147 148 149 150 151 152 153
			FORMAT_MESSAGE_FROM_SYSTEM |
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			code,
			0, // Default language
			(LPTSTR) &msgBuf,
			sizeof(msgBuf),
			NULL);
	/*FIXME: should convert from TCHAR to UTF8 */
154
#endif
155 156 157
	return (const char *)msgBuf;
}

158 159

int belle_sip_thread_key_create(belle_sip_thread_key_t *key, void (*destructor)(void*) ){
160 161 162
#ifdef HAVE_COMPILER_TLS
	*key = (belle_sip_thread_key_t)&current_thread_data;
#else
163 164 165 166 167
	*key=TlsAlloc();
	if (*key==TLS_OUT_OF_INDEXES){
		belle_sip_error("TlsAlloc(): TLS_OUT_OF_INDEXES.");
		return -1;
	}
168
#endif
169 170 171 172
	return 0;
}

int belle_sip_thread_setspecific(belle_sip_thread_key_t key,const void *value){
173 174 175 176
#ifdef HAVE_COMPILER_TLS
	current_thread_data = value;
	return 0;
#else
177
	return TlsSetValue(key,(void*)value) ? 0 : -1;
178
#endif
179 180 181
}

const void* belle_sip_thread_getspecific(belle_sip_thread_key_t key){
182 183 184
#ifdef HAVE_COMPILER_TLS
	return current_thread_data;
#else
185
	return TlsGetValue(key);
186
#endif
187 188 189
}

int belle_sip_thread_key_delete(belle_sip_thread_key_t key){
190 191 192 193
#ifdef HAVE_COMPILER_TLS
	current_thread_data = NULL;
	return 0;
#else
194
	return TlsFree(key) ? 0 : -1;
195
#endif
196 197
}

198
#ifndef BELLE_SIP_WINDOWS_DESKTOP
199 200 201 202 203 204 205 206
void belle_sip_sleep(unsigned int ms) {
	HANDLE sleepEvent = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
	if (!sleepEvent)
		return;
	WaitForSingleObjectEx(sleepEvent, ms, FALSE);
}
#endif

207 208
#else

Simon Morlat's avatar
Simon Morlat committed
209 210
#include <signal.h>

211
int belle_sip_init_sockets(){
Simon Morlat's avatar
Simon Morlat committed
212
	signal(SIGPIPE,SIG_IGN);
213 214 215 216 217 218
	return 0;
}

void belle_sip_uninit_sockets(){
}

219 220 221 222
int belle_sip_socket_set_nonblocking(belle_sip_socket_t sock){
	return fcntl (sock, F_SETFL, fcntl(sock,F_GETFL) | O_NONBLOCK);
}

Simon Morlat's avatar
Simon Morlat committed
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
int belle_sip_socket_set_dscp(belle_sip_socket_t sock, int ai_family, int dscp){
	int tos;
	int proto;
	int value_type;
	int retval;
	
	tos = (dscp << 2) & 0xFC;
	switch (ai_family) {
		case AF_INET:
			proto=IPPROTO_IP;
			value_type=IP_TOS;
		break;
		case AF_INET6:
			proto=IPPROTO_IPV6;
#ifdef IPV6_TCLASS /*seems not defined by my libc*/
			value_type=IPV6_TCLASS;
#else
			value_type=IP_TOS;
#endif
		break;
		default:
			belle_sip_error("Cannot set DSCP because socket family is unspecified.");
			return -1;
	}
	retval = setsockopt(sock, proto, value_type, (const char*)&tos, sizeof(tos));
	if (retval==-1)
		belle_sip_error("Fail to set DSCP value on socket: %s",belle_sip_get_socket_error_string());
	return retval;
}

Simon Morlat's avatar
Simon Morlat committed
253 254
#endif

255 256 257 258 259 260 261 262 263 264

int belle_sip_socket_enable_dual_stack(belle_sip_socket_t sock){
	int value=0;
	int err=setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&value, sizeof(value));
	if (err==-1){
		belle_sip_warning("belle_sip_socket_enable_dual_stack: setsockopt(IPV6_ONLY) failed: %s",belle_sip_get_socket_error_string());
	}
	return err;
}

265
#if defined(ANDROID) || defined(_WIN32)
266

267 268 269 270 271 272
/*
 * SHAME !!! bionic's getaddrinfo does not implement the AI_V4MAPPED flag !
 * It is declared in header file but rejected by the implementation.
 * The code below is to emulate a _compliant_ getaddrinfo for android.
**/

273 274 275 276 277
/**
 * SHAME AGAIN !!! Win32's implementation of getaddrinfo is bogus !
 * it is not able to return an IPv6 addrinfo from an IPv4 address when AI_V4MAPPED is set !
**/

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
struct addrinfo *_belle_sip_alloc_addrinfo(int ai_family, int socktype, int proto){
	struct addrinfo *ai=(struct addrinfo*)belle_sip_malloc0(sizeof(struct addrinfo));
	ai->ai_family=ai_family;
	ai->ai_socktype=socktype;
	ai->ai_protocol=proto;
	ai->ai_addrlen=AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
	ai->ai_addr=(struct sockaddr *) belle_sip_malloc0(ai->ai_addrlen);
	return ai;
}

struct addrinfo *convert_to_v4mapped(const struct addrinfo *ai){
	struct addrinfo *res=NULL;
	const struct addrinfo *it;
	struct addrinfo *v4m=NULL;
	struct addrinfo *last=NULL;
	
	for (it=ai;it!=NULL;it=it->ai_next){
		struct sockaddr_in6 *sin6;
		struct sockaddr_in *sin;
		v4m=_belle_sip_alloc_addrinfo(AF_INET6, it->ai_socktype, it->ai_protocol);
298
		v4m->ai_flags|=AI_V4MAPPED;
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
		sin6=(struct sockaddr_in6*)v4m->ai_addr;
		sin=(struct sockaddr_in*)it->ai_addr;
		sin6->sin6_family=AF_INET6;
		((uint8_t*)&sin6->sin6_addr)[10]=0xff;
		((uint8_t*)&sin6->sin6_addr)[11]=0xff;
		memcpy(((uint8_t*)&sin6->sin6_addr)+12,&sin->sin_addr,4);
		sin6->sin6_port=sin->sin_port;
		if (last){
			last->ai_next=v4m;
		}else{
			res=v4m;
		}
		last=v4m;
	}
	return res;
}
315

316 317 318 319 320 321 322 323 324 325 326 327
struct addrinfo *addrinfo_concat(struct addrinfo *a1, struct addrinfo *a2){
	struct addrinfo *it;
	struct addrinfo *last=NULL;
	for (it=a1;it!=NULL;it=it->ai_next){
		last=it;
	}
	if (last){
		last->ai_next=a2;
		return a1;
	}else
		return a2;
}
328

329 330 331 332 333 334 335 336 337
int belle_sip_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res){
	if (hints && hints->ai_family!=AF_INET && hints->ai_flags & AI_V4MAPPED){
		struct addrinfo *res6=NULL;
		struct addrinfo *res4=NULL;
		struct addrinfo lhints={0};
		int err;
		
		if (hints) memcpy(&lhints,hints,sizeof(lhints));
		
338
		lhints.ai_flags &= ~(AI_ALL | AI_V4MAPPED); /*remove the unsupported flags*/
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
		if (hints->ai_flags & AI_ALL){
			lhints.ai_family=AF_INET6;
			err=getaddrinfo(node, service, &lhints, &res6);
		}
		lhints.ai_family=AF_INET;
		err=getaddrinfo(node, service, &lhints, &res4);
		if (err==0){
			struct addrinfo *v4m=convert_to_v4mapped(res4);
			freeaddrinfo(res4);
			res4=v4m;
		}
		*res=addrinfo_concat(res6,res4);
		if (*res) err=0;
		return err;
	}
	return getaddrinfo(node, service, hints, res);
}
356

357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
void _belle_sip_freeaddrinfo(struct addrinfo *res){
	struct addrinfo *it,*next_it;
	for(it=res;it!=NULL;it=next_it){
		next_it=it->ai_next;
		belle_sip_free(it->ai_addr);
		belle_sip_free(it);
	}
}

void belle_sip_freeaddrinfo(struct addrinfo *res){
	struct addrinfo *it,*previt=NULL;
	struct addrinfo *allocated_by_belle_sip=NULL;
	for(it=res;it!=NULL;it=it->ai_next){
		if (it->ai_flags & AI_V4MAPPED){
			allocated_by_belle_sip=it;
			if (previt) previt->ai_next=NULL;
373
			break;
374 375 376
		}
		previt=it;
	}
377
	if (res!=allocated_by_belle_sip) freeaddrinfo(res);
378 379 380 381 382 383 384 385 386 387 388 389 390 391
	if (allocated_by_belle_sip) _belle_sip_freeaddrinfo(allocated_by_belle_sip);
}

#else

int belle_sip_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res){
	return getaddrinfo(node, service, hints, res);
}

void belle_sip_freeaddrinfo(struct addrinfo *res){
	freeaddrinfo(res);
}

#endif