text: /***************************************************************************
      begin                : Fri Feb 14 2003
      copyright            : (C) 2003 - 2009 by Alper Akcan
      email                : alper.akcan@gmail.com
   ***************************************************************************/
  
  /***************************************************************************
   *                                                                         *
   *   This program is free software; you can redistribute it and/or modify  *
   *   it under the terms of the GNU Lesser General Public License as        *
   *   published by the Free Software Foundation; either version 2.1 of the  *
   *   License, or (at your option) any later version.                       *
   *                                                                         *
   ***************************************************************************/
  
  #include "xynth_.h"
  
  #if !defined(CONFIG_IPC_UDS) && !defined(CONFIG_IPC_TCP) && !defined(CONFIG_IPC_PIPE)
  	#error "You must select at least one of CONFIG_IPC_UDS, CONFIG_IPC_TCP, CONFIG_IPC_PIPE"
  #endif
  
  typedef struct s_socket_data_name_s {
  	char *name;
  	S_SOC_DATA data;
  } s_socket_data_name_t;
  
  const char * s_socket_data_to_name (S_SOC_DATA sdata)
  {
  	static s_socket_data_name_t dnames[] = {
  		{"SOC_DATA_NOTHING", SOC_DATA_NOTHING},
  		{"SOC_DATA_NEW", SOC_DATA_NEW},
  		{"SOC_DATA_SHOW", SOC_DATA_SHOW},
  		{"SOC_DATA_CLOSE", SOC_DATA_CLOSE},
  		{"SOC_DATA_CLOSE_SERVER", SOC_DATA_CLOSE_SERVER},
  		{"SOC_DATA_EVENT", SOC_DATA_EVENT},
  		{"SOC_DATA_EXPOSE", SOC_DATA_EXPOSE},
  		{"SOC_DATA_DISPLAY", SOC_DATA_DISPLAY},
  		{"SOC_DATA_FORMDRAW", SOC_DATA_FORMDRAW},
  		{"SOC_DATA_CONFIGURE", SOC_DATA_CONFIGURE},
  		{"SOC_DATA_DESKTOP", SOC_DATA_DESKTOP},
  	};
  	static unsigned int dsize = sizeof(dnames) / sizeof(s_socket_data_name_t);
  	unsigned int i;
  	for (i = 0; i < dsize; i++) {
  		if (dnames[i].data == sdata) {
  			return dnames[i].name;
  		}
  	}
  	return "Unknown";
  }
  
  #define s_socket_recv(a, b, c)	if (s_socket_api_recv(a, b, c) != c) { return -1; }
  #define s_socket_send(a, b, c)	if (s_socket_api_send(a, b, c) != c) { return -1; }
  
  int s_socket_request_new (s_window_t *window, int soc)
  {
  	int pid;
  	pid = (window->type & (WINDOW_TYPE_TEMP | WINDOW_TYPE_CHILD)) ? window->parent->id : -1;
  	s_socket_send(soc, &window->type, sizeof(s_window_type_t));
  	s_socket_send(soc, &pid, sizeof(int));
  	s_socket_send(soc, window->surface->buf, sizeof(s_rect_t));
  	s_socket_recv(soc, window->surface->buf, sizeof(s_rect_t));
  	s_socket_recv(soc, window->surface->win, sizeof(s_rect_t));
  	return 0;
  }
  
  int s_socket_request_display (s_window_t *window, int soc)
  {
  	s_soc_data_display_t *data;
  	data = (s_soc_data_display_t *) s_calloc(1, sizeof(s_soc_data_display_t));
  
  	if (s_socket_api_recv(soc, data, sizeof(s_soc_data_display_t)) != sizeof(s_soc_data_display_t)) {
  		s_free(data);
  		return -1;
  	}
  
  	window->surface->bytesperpixel = data->bytesperpixel;
  	window->surface->bitsperpixel = data->bitsperpixel;
  	window->surface->colors = data->colors;
  	window->surface->blueoffset = data->blueoffset;
  	window->surface->greenoffset = data->greenoffset;
  	window->surface->redoffset = data->redoffset;
  	window->surface->bluelength = data->bluelength;
  	window->surface->greenlength = data->greenlength;
  	window->surface->redlength = data->redlength;
  	window->surface->bluemask = data->bluemask;
  	window->surface->greenmask = data->greenmask;
  	window->surface->redmask = data->redmask;
  
  	window->surface->linear_buf = (unsigned char *) data->linear_buf;
  	window->surface->matrix = (unsigned char *) data->matrix;
  
  	window->surface->linear_mem_size = data->linear_mem_size;
  	window->surface->linear_mem_base = data->linear_mem_base;
  	window->surface->linear_buf_width = data->linear_buf_width;
  	window->surface->linear_buf_pitch = data->linear_buf_pitch;
  	window->surface->linear_buf_height = data->linear_buf_height;
  	window->surface->shm_mid = data->shm_mid;
  	window->id = data->id;
  
  	window->surface->shm_sid = data->shm_sid;
  	window->surface->need_expose = data->need_expose;
  
  	window->surface->device = strdup(data->device);
  
  	s_free(data);
  	return 0;
  }
  
  int s_socket_request_configure (s_window_t *window, int soc, int form)
  {
  	s_soc_data_configure_t *data;
  	data = (s_soc_data_configure_t *) s_calloc(1, sizeof(s_soc_data_configure_t));
  
  	data->form = (form) ? WINDOW_TYPE_NOFORM : 0;
  	data->rnew = *(window->surface->buf);
  	data->resizeable = window->resizeable;
  	data->alwaysontop = window->alwaysontop;
  	data->cursor = window->cursor;
  	if (window->title != NULL) {
  		strncpy(data->title, window->title, S_TITLE_MAX);
  	}
  	data->title[S_TITLE_MAX - 1] = '\0';
  
  	if (s_socket_api_send(soc, data, sizeof(s_soc_data_configure_t)) != sizeof(s_soc_data_configure_t)) {
  		s_free(data);
  		return -1;
  	}
  
  	s_free(data);
  	return 0;
  }
  
  int s_socket_request_stream (s_window_t *window, int soc, s_rect_t *coor)
  {
  	s_soc_data_stream_t *data;
  	data = (s_soc_data_stream_t *) s_calloc(1, sizeof(s_soc_data_stream_t));
  	data->bitspp = window->surface->bitsperpixel;
  	data->rect.x = coor->x + window->surface->buf->x;
  	data->rect.y = coor->y + window->surface->buf->y;
  	data->rect.w = coor->w;
  	data->rect.h = coor->h;
  	if (window->surface->need_expose & SURFACE_NEEDSTREAM) {
  		data->blen = (unsigned int) (window->surface->bytesperpixel * coor->w * coor->h);
  		data->buf = (char *) s_malloc(data->blen + 1);
  		s_getbox(window->surface, coor->x, coor->y, coor->w, coor->h, data->buf);
  	} else {
  		data->blen = 0;
  	}
  	if (s_socket_api_send(soc, data, sizeof(s_soc_data_stream_t)) != sizeof(s_soc_data_stream_t)) {
  		s_free(data->buf);
  		s_free(data);
  		return -1;
  	}
  	if (data->blen != 0) {
  		if (s_socket_api_send(soc, data->buf, data->blen) != data->blen) {
  			s_free(data->buf);
  			s_free(data);
  			return -1;
  		}
  		s_free(data->buf);
  	}
  	s_free(data);
  	return 0;
  }
  
  int s_socket_request_show (s_window_t *window, int soc, int id, char *title, int show)
  {
  	s_soc_data_show_t *data;
  	data = (s_soc_data_show_t *) s_calloc(1, sizeof(s_soc_data_show_t));
  	data->id = id;
  	data->show = show;
  	if (title != NULL) {
  		strncpy(data->title, title, S_TITLE_MAX);
  	}
  	data->title[S_TITLE_MAX - 1] = '\0';
  	if (s_socket_api_send(soc, data, sizeof(s_soc_data_show_t)) != sizeof(s_soc_data_show_t)) {
  		s_free(data);
  		return -1;
  	}
  	s_free(data);
  	return 0;
  }
  
  int s_socket_request_event (s_window_t *window, int soc, s_event_t *event)
  {
  	s_soc_data_event_t *data;
  	data = (s_soc_data_event_t *) s_calloc(1, sizeof(s_soc_data_event_t));
  	data->type = event->type;
  	data->keybd.ascii = event->keybd->ascii;
  	data->keybd.button = event->keybd->button;
  	data->keybd.keycode = event->keybd->keycode;
  	data->keybd.scancode = event->keybd->scancode;
  	if (s_socket_api_send(soc, data, sizeof(s_soc_data_event_t)) != sizeof(s_soc_data_event_t)) {
  		s_free(data);
  		return -1;
  	}
  	s_free(data);
  	return 0;
  }
  
  int s_socket_request (s_window_t *window, S_SOC_DATA req, ...)
  {
  	int id;
  	int show;
  	va_list ap;
  	int ret = 0;
  	char *title;
  	s_window_type_t form;
  	s_rect_t *coor;
  	s_event_t *event;
  	struct pollfd pollfd;
  
  again:	if (window->running <= 0) {
  		return -1;
  	}
  
  	s_thread_mutex_lock(window->socket_mutex);
  
  	pollfd.fd = window->soc;
  	pollfd.events = POLLOUT | POLLIN;
  	pollfd.revents = 0;
  
  	if (s_socket_api_poll(&pollfd, 1, -1) <= 0) {
  		goto err0;
  	}
  	if (pollfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
  		goto err0;
  	}
  	if (pollfd.revents & POLLIN) {
  		s_thread_mutex_unlock(window->socket_mutex);
  		s_socket_listen_parse(window, pollfd.fd);
  		goto again;
  	}
  	if (pollfd.revents != POLLOUT) {
  		debugf(DCLI, "[%d] Error occured when requesting (%d) from server", window->id, req);
  		goto err0;
  	}
  	if (s_socket_api_send(pollfd.fd, &req, sizeof(req)) != sizeof(req)) {
  		debugf(DCLI, "[%d] Error occured when requesting (%d) from server", window->id, req);
  		goto err0;
  	}
  
  #if 0
  	debugf(DCLI, "[%d] Requesting 0x%08x (%s) from server", window->id, req, s_socket_data_to_name(req));
  #endif
  
  	switch (req) {
  		case SOC_DATA_NEW:
  			ret = s_socket_request_new(window, pollfd.fd);
  			break;
  		case SOC_DATA_DISPLAY:
  			ret = s_socket_request_display(window, pollfd.fd);
  			break;
  		case SOC_DATA_CONFIGURE:
  			va_start(ap, req);
  			form = (s_window_type_t) va_arg(ap, s_window_type_t);
  			ret = s_socket_request_configure(window, pollfd.fd, (form) ? 1 : 0);
  			va_end(ap);
  			break;
  		case SOC_DATA_EXPOSE:
  			va_start(ap, req);
  			coor = (s_rect_t *) va_arg(ap, s_rect_t *);
  			ret = s_socket_request_stream(window, pollfd.fd, coor);
  			va_end(ap);
  			break;
  		case SOC_DATA_SHOW:
  			va_start(ap, req);
  			id = (int) va_arg(ap, int);
  			title = (char *) va_arg(ap, char *);
  			show = (int) va_arg(ap, int);
  			ret = s_socket_request_show(window, pollfd.fd, id, title, show);
  			va_end(ap);
  			break;
  		case SOC_DATA_EVENT:
  			va_start(ap, req);
  			event = (s_event_t *) va_arg(ap, s_event_t *);
  			ret = s_socket_request_event(window, pollfd.fd, event);
  			va_end(ap);
  			break;
  		case SOC_DATA_CLOSE:
  		case SOC_DATA_CLOSE_SERVER:
  		case SOC_DATA_DESKTOP:
  		case SOC_DATA_NOTHING:
  		case SOC_DATA_FORMDRAW:
  			break;
  		default:
  			debugf(DSER, "Unhandled request 0x%08x (%s), this should not happen", req, s_socket_data_to_name(req));
  			goto err0;
  	}
  
  	s_thread_mutex_unlock(window->socket_mutex);
  	return ret;
  err0:	s_thread_mutex_unlock(window->socket_mutex);
  	return -1;
  }
  
  int s_socket_listen_event (s_window_t *window, int soc)
  {
  	s_event_type_t dtype;
  	s_soc_data_event_t *data;
  	data = (s_soc_data_event_t *) s_calloc(1, sizeof(s_soc_data_event_t));
  
  	if (s_socket_api_recv(soc, data, sizeof(s_soc_data_event_t)) != sizeof(s_soc_data_event_t)) {
  		s_free(data);
  		return -1;
  	}
  
  	dtype = data->type & (EVENT_TYPE_MOUSE_ENTER | EVENT_TYPE_MOUSE_EXIT);
  	if ((dtype == 0) ||
  	    ((dtype != 0) &&
  	     (dtype != window->mouse_entered))) {
  		window->mouse_entered = dtype;
  		window->event->type = data->type;
  		*(window->event->mouse) = data->mouse;
  		*(window->event->keybd) = data->keybd;
  		s_event_changed(window);
  	}
  
  	s_free(data);
  	return 0;
  }
  
  int s_socket_listen_close (s_window_t *window, int soc)
  {
          window->running = 0;
          return 0;
  }
  
  int s_socket_listen_expose (s_window_t *window, int soc)
  {
  	int p_old;
  	s_event_type_t change;
  	s_rect_t r_old;
  	s_soc_data_expose_t *data;
  	data = (s_soc_data_expose_t *) s_calloc(1, sizeof(s_soc_data_expose_t));
  
  	if (s_socket_api_recv(soc, data, sizeof(s_soc_data_expose_t)) != sizeof(s_soc_data_expose_t)) {
  		s_free(data);
  		return -1;
  	}
  
  	p_old = window->pri;
  	r_old = *(window->surface->win);
  
  	window->pri = data->pri;
  	*(window->surface->buf) = data->buf;
  	*(window->surface->win) = data->win;
  	window->surface->linear_buf_width = data->linear_buf_width;
  	window->surface->linear_buf_pitch = data->linear_buf_pitch;
  	window->surface->linear_buf_height = data->linear_buf_height;
  
  	/* configure event */
  	change = 0;
  	if (r_old.x != window->surface->win->x) { change |= EVENT_TYPE_CONFIG_X; }
  	if (r_old.y != window->surface->win->y) { change |= EVENT_TYPE_CONFIG_Y; }
  	if (r_old.w != window->surface->win->w) { change |= EVENT_TYPE_CONFIG_W; }
  	if (r_old.h != window->surface->win->h) { change |= EVENT_TYPE_CONFIG_H; }
  	if (change != 0) {
  		window->event->type = EVENT_TYPE_CONFIG | change;
  		window->event->expose->rect->x = window->surface->buf->x;
  		window->event->expose->rect->y = window->surface->buf->y;
  		window->event->expose->rect->w = window->surface->buf->w;
  		window->event->expose->rect->h = window->surface->buf->h;
  		s_event_changed(window);
  	}
  	/* map event */
  	if (p_old == -1 && window->pri >= 0) {
  		window->event->type = EVENT_TYPE_MAP | EVENT_TYPE_MAPPED;
  		s_event_changed(window);
  	} else if (window->pri == -1 && p_old >= 0) {
  		window->event->type = EVENT_TYPE_MAP | EVENT_TYPE_UNMAPPED;
  		s_event_changed(window);
  	}
  	/* focus event */
  	if ((p_old != window->pri) &&
  	    ((p_old == 0) || (window->pri == 0))) {
  		window->event->type = EVENT_TYPE_FOCUS;
  		window->event->type |= (window->pri == 0) ? EVENT_TYPE_FOCUS_IN : EVENT_TYPE_FOCUS_OUT;
  		window->event->expose->rect->x = window->surface->win->x;
  		window->event->expose->rect->y = window->surface->win->y;
  		window->event->expose->rect->w = window->surface->win->w;
  		window->event->expose->rect->h = window->surface->win->h;
  		s_event_changed(window);
  	}
  	/* expose event */
  	if (data->changed.w > 0 &&
  	    data->changed.h > 0) {
  		window->event->type = EVENT_TYPE_EXPOSE;
  		window->event->expose->rect->x = data->changed.x;
  		window->event->expose->rect->y = data->changed.y;
  		window->event->expose->rect->w = data->changed.w;
  		window->event->expose->rect->h = data->changed.h;
  		s_event_changed(window);
  	}
  
          s_free(data);
  	return 0;
  }
  
  int s_socket_listen_desktop (s_window_t *window, int soc)
  {
  	int i;
          s_event_t *event;
  	s_soc_data_desktop_t *data;
          s_desktop_client_t *desktopc;
  
  	data = (s_soc_data_desktop_t *) s_calloc(1, sizeof(s_soc_data_desktop_t));
  	if (s_socket_api_recv(soc, data, sizeof(s_soc_data_desktop_t)) != sizeof(s_soc_data_desktop_t)) {
  		s_free(data);
  		return -1;
  	}
  
          s_event_init(&event);
  	event->type = EVENT_TYPE_DESKTOP;
  
  	for (i = 0; i < data->count; i++) {
  		desktopc = (s_desktop_client_t *) s_malloc(sizeof(s_desktop_client_t));
  		desktopc->id = data->client[i].id;
  		desktopc->pri = data->client[i].pri;
  		desktopc->title = strdup(data->client[i].title);
  		s_list_add(event->desktop->clients, desktopc, -1);
  	}
  	s_eventq_add(window, event);
  	s_free(data);
  
  	return 0;
  }
  
  int s_socket_listen_parse (s_window_t *window, int soc)
  {
          int ret = 0;
  	struct pollfd pollfd;
  	S_SOC_DATA req = SOC_DATA_NOTHING;
  
          s_thread_mutex_lock(window->socket_mutex);
  
  	pollfd.fd = soc;
  	pollfd.events = POLLIN;
  	pollfd.revents = 0;
  
  	if ((s_socket_api_poll(&pollfd, 1, 0) <= 0) ||
  	    (pollfd.revents != POLLIN)) {
  	        s_thread_mutex_unlock(window->socket_mutex);
  	        return 0;
  	}
  	if (s_socket_api_recv(soc, &req, sizeof(req)) <= 0) {
  		goto err0;
  	}
  
  #if 0
  	debugf(DCLI, "[%d] Received 0x%08x (%s) from server", window->id, req, s_socket_data_to_name(req));
  #endif
  
  	switch (req) {
  		case SOC_DATA_EVENT:
  			ret = s_socket_listen_event(window, soc);
  			break;
  		case SOC_DATA_CLOSE:
  			ret = s_socket_listen_close(window, soc);
  			break;
  		case SOC_DATA_EXPOSE:
  			ret = s_socket_listen_expose(window, soc);
  			break;
  		case SOC_DATA_DESKTOP:
  			ret = s_socket_listen_desktop(window, soc);
  			break;
  		case SOC_DATA_NEW:
  		case SOC_DATA_SHOW:
  		case SOC_DATA_NOTHING:
  		case SOC_DATA_DISPLAY:
  		case SOC_DATA_FORMDRAW:
  		case SOC_DATA_CONFIGURE:
  		case SOC_DATA_CLOSE_SERVER:
  			break;
  		default:
  			debugf(DSER, "Unhandled request 0x%08x (%s), this should not happen", req, s_socket_data_to_name(req));
  			goto err0;
  			break;
  	}
  
          s_thread_mutex_unlock(window->socket_mutex);
  	return ret;
  err0:	s_thread_mutex_unlock(window->socket_mutex);
  	return -1;
  }
  
  int s_socket_listen_wait (s_window_t *window, int timeout)
  {
          int i;
          int len;
  	int ret;
  	int retval;
  	long long tv[2];
  	s_timer_t *tmr;
  	s_pollfd_t *pfd;
  	struct pollfd *polfd;
  
  	if (window->running <= 0) {
  		return -1;
  	}
  
  	s_thread_mutex_lock(window->pollfds->mut);
  	len = window->pollfds->list->nb_elt;
          polfd = (struct pollfd *) s_malloc(len * sizeof(struct pollfd));
          for (i = 0; i < len; i++) {
  		pfd = (s_pollfd_t *) s_list_get(window->pollfds->list, i);
  		polfd[i].fd = pfd->fd;
  		polfd[i].events = POLLIN;
  		polfd[i].revents = 0;
  	}
  	s_thread_mutex_unlock(window->pollfds->mut);
  
  	timeout = -1;
  	i = 0;
  	s_thread_mutex_lock(window->timers->mut);
  	while (!s_list_eol(window->timers->timers, i)) {
  		tmr = (s_timer_t *) s_list_get(window->timers->timers, i);
  		if (tmr->timeval > 0) {
  			if (tmr->interval <= 0) {
  				tmr->interval = tmr->timeval;
  			}
  			if (timeout <= 0) {
  				timeout = tmr->interval;
  			}
  			if (tmr->timeval < timeout) {
  				timeout = tmr->interval;
  			}
  		} else {
  			s_list_remove(window->timers->timers, i);
  			continue;
  		}
  		i++;
  	}
  	s_thread_mutex_unlock(window->timers->mut);
  
  	tv[0] = s_gettimeofday();
  	ret = s_socket_api_poll(polfd, len, timeout);
  	tv[1] = s_gettimeofday();
  
  	retval = 0;
  	switch (ret) {
  		case 0:
  			goto end;
  		case -1:
  			retval = -1;
  			goto end;
  		default:
  			for (i = 0; i < len; i++) {
  				pfd = s_pollfd_find(window, polfd[i].fd);
  				if (pfd == NULL) {
  					continue;
  				}
  				if (polfd[i].revents & (POLLHUP | POLLERR | POLLNVAL)) {
  err:					if (pfd->pf_err != NULL) {
  						retval = pfd->pf_err(window, pfd);
  						goto end;
  					}
  				} else if (polfd[i].revents == POLLIN) {
  					if (pfd->pf_in != NULL) {
  						if ((retval = pfd->pf_in(window, pfd)) < 0) {
  							debugf(DSER, "pfd->in(window, polfd[%d].fd) < 0) Calling pfd->ierr if exists", i);
  							goto err;
  						}
  						goto end;
  					}
  				}
  			}
  	}
  
  end:	i = 0;
  	s_thread_mutex_lock(window->timers->mut);
  	while (!s_list_eol(window->timers->timers, i)) {
  		tmr = (s_timer_t *) s_list_get(window->timers->timers, i);
  		tmr->interval -= (tv[1] - tv[0]);
  		i++;
  	}
  	i = 0;
  	while (!s_list_eol(window->timers->timers, i)) {
  		tmr = (s_timer_t *) s_list_get(window->timers->timers, i);
  		if (tmr->interval <= 0) {
  			s_event_t *e;
  			s_event_init(&e);
  			e->type = EVENT_TYPE_TIMER;
  			e->timer = tmr;
  			s_eventq_add(window, e);
  		}
  		i++;
  	}
  	s_thread_mutex_unlock(window->timers->mut);
  
  	s_free(polfd);
  	return retval;
  }
  
  int s_socket_uninit (s_window_t *window, s_pollfd_t *pfd)
  {
  	s_thread_mutex_destroy(window->socket_mutex);
  	s_socket_api_close(pfd->fd);
  	return 0;
  }
  
  int s_socket_in_f (s_window_t *window, s_pollfd_t *pfd)
  {
  	return s_socket_listen_parse(window, pfd->fd);
  }
  
  int s_socket_ierr_f (s_window_t *window, s_pollfd_t *pfd)
  {
  	debugf(DCLI, "[%d] Server side closed the connection", window->id);
  	return -1;
  }
  
  int s_socket_inw_f (s_window_t *window, s_pollfd_t *pfd)
  {
          int w;
  	s_pipe_api_read(pfd->fd, &w, sizeof(int));
  	return 0;
  }
  
  int s_socket_ierrw_f (s_window_t *window, s_pollfd_t *pfd)
  {
  	return -1;
  }
  
  int s_socket_api_closew_f (s_window_t *window, s_pollfd_t *pfd)
  {
  	s_pipe_api_close(pfd->fd);
  	s_pipe_api_close(window->wsoc);
  	return 0;
  }
  
  int s_socket_init_uds (s_window_t *window)
  {
  #if defined(CONFIG_IPC_UDS)
  	int fd;
          struct sockaddr_un server = {AF_UNIX, S_SERVER_SOC_NAME};
  
  	fd = s_socket_api_socket(AF_UNIX, SOCK_STREAM, 0);
          if (fd < 0) {
  		goto err0;
  	}
  	if (s_socket_api_connect(fd, (s_sockaddr_t *) &server, sizeof(server)) == -1) {
  		goto err1;
  	}
  	debugf(DCLI, "Connected to server via UDS (%s)", S_SERVER_SOC_NAME);
  	return fd;
  
  err1:	s_socket_api_close(fd);
  err0:	return -1;
  #else
  	return -1;
  #endif
  }
  
  int s_socket_init_tcp (s_window_t *window)
  {
  #if defined(CONFIG_IPC_TCP)
          int fd;
  	struct sockaddr_in server;
  	server.sin_family = AF_INET;
  	server.sin_addr.s_addr = inet_addr(S_SERVER_SOC_ADDR);
  	server.sin_port = htons(S_SERVER_SOC_PORT);
  
          fd = s_socket_api_socket(AF_INET, SOCK_STREAM, 0);
          if (fd < 0) {
  		goto err0;
  	}
  	if (s_socket_api_connect(fd, (s_sockaddr_t *) &server, sizeof(server)) == -1) {
  		goto err1;
  	}
  	debugf(DCLI, "Connected to server via TCP (%s:%d)", S_SERVER_SOC_ADDR, S_SERVER_SOC_PORT);
  	return fd;
  err1:	s_socket_api_close(fd);
  err0:	return -1;
  #else
  	return -1;
  #endif
  }
  
  int s_socket_init_pipe (s_window_t *window)
  {
  #if defined(CONFIG_IPC_PIPE)
  	int fd;
          s_sockaddr_t server = {AF_PIPE, S_SERVER_SOC_PIPE};
  
  	fd = s_socket_api_socket(AF_PIPE, SOCK_STREAM, 0);
          if (fd < 0) {
  		goto err0;
  	}
  	if (s_socket_api_connect(fd, (s_sockaddr_t *) &server, sizeof(server)) == -1) {
  		goto err1;
  	}
  	debugf(DCLI, "Connected to server via PIPE (%s)", S_SERVER_SOC_PIPE);
  	return fd;
  err1:	s_socket_api_close(fd);
  err0:	return -1;
  #else
  	return -1;
  #endif
  }
  
  int s_socket_init_wakeup (s_window_t *window)
  {
  	int fd[2];
  	s_pollfd_t *pfd;
  
  	if (s_pollfd_init(&pfd)) {
  		goto err0;
  	}
  	if (s_pipe_api_pipe(fd)) {
  		goto err1;
  	}
  
  	window->wsoc = fd[1];
  	pfd->fd = fd[0];
  	pfd->pf_in = s_socket_inw_f;
  	pfd->pf_err = s_socket_ierrw_f;
  	pfd->pf_close = s_socket_api_closew_f;
  	if (!s_pollfd_add(window, pfd)) {
  		goto err2;
  	}
  
  	return 0;
  err2:	s_pipe_api_close(fd[0]);
  	s_pipe_api_close(fd[1]);
  err1:	s_pollfd_uninit(pfd);
  err0:	return -1;
  }
  
  int s_socket_init (s_window_t *window)
  {
  	int fd;
  	s_pollfd_t *pfd;
  
  	if (((fd = s_socket_init_uds(window)) < 0) &&
  	    ((fd = s_socket_init_tcp(window)) < 0) &&
  	    ((fd = s_socket_init_pipe(window)) < 0)) {
  		goto err0;
  	}
  	if (s_socket_init_wakeup(window)) {
  		goto err0;
  	}
  	if (s_pollfd_init(&pfd)) {
  		goto err0;
  	}
  
  	window->soc = fd;
          pfd->fd = fd;
          pfd->pf_in = s_socket_in_f;
          pfd->pf_err = s_socket_ierr_f;
          pfd->pf_close = s_socket_uninit;
  
  	if (!s_pollfd_add(window, pfd)) {
  		goto err1;
  	}
  
  	if (s_thread_mutex_init(&(window->socket_mutex))) {
  		goto err0;
  	}
  
  	return 0;
  
  err1:	s_pollfd_uninit(pfd);
  err0:	return -1;
  }
  