//-------------------------------------------------------------------------
// Webserver-Thread for each connection
//-------------------------------------------------------------------------
void *WebThread(void *args) {
	TWebserverConnectionArgs *newConn = (TWebserverConnectionArgs *) args;
	if (!newConn) {
		dperror("WebThread called without arguments!\n");
		return NULL;
	}

	bool is_threaded = newConn->is_treaded;
	if (is_threaded)
		log_level_printf(1, "++ Thread 0x06%X gestartet\n", (int) pthread_self());

	// (1) create & init Connection
	CWebserver *ws = newConn->WebserverBackref;
	if (!ws) {
		dperror("WebThread CWebserver error!\n");
		return NULL;
	}

	CWebserverConnection *con = new CWebserverConnection(ws);
	if (!con) {
		dperror("WebThread CWebserverConnection error!\n");
		return NULL;
	}

	con->Request.UrlData["clientaddr"] = newConn->ySock->get_client_ip(); // TODO:here?
	con->sock = newConn->ySock; // give socket reference
	newConn->ySock->handling = true; // dont handle this socket now be webserver main loop

	// (2) handle the connection
	con->HandleConnection();

	// (3) end connection handling
#ifdef Y_CONFIG_FEATURE_KEEP_ALIVE
	if(!con->keep_alive)
		log_level_printf(2,"FD SHOULD CLOSE sock:%d!!!\n",con->sock->get_socket());
	else
		ws->addSocketToMasterSet(con->sock->get_socket()); // add to master set
#endif
	if (!con->keep_alive)
		con->sock->isValid = false;
	con->sock->handling = false; // socket can be handled by webserver main loop (select) again

#ifndef Y_CONFIG_FEATURE_KEEP_ALIVE
	delete newConn->ySock;
	newConn->ySock = NULL;
#endif

	// (4) end thread
	delete con;
	int thread_number = newConn->thread_number;
	delete newConn;
	if (is_threaded) {
		log_level_printf(1, "-- Thread 0x06%X beendet\n", (int) pthread_self());
		ws->clear_Thread_List_Number(thread_number);
		pthread_exit( NULL);
	}
	return NULL;
}
//-----------------------------------------------------------------------------
// A new Connection is established to newSock. Create a (threaded) Connection
// and handle the Request.
//-----------------------------------------------------------------------------
bool CWebserver::handle_connection(CySocket *newSock) {
	void *WebThread(void *args); //forward declaration

	// create arguments
	TWebserverConnectionArgs *newConn = new TWebserverConnectionArgs;
	if (!newConn) {
		dperror("CWebserver TWebserverConnectionArgs error!\n");
		return false;
	}
	newConn->ySock = newSock;
	newConn->ySock->handling = true;
	newConn->WebserverBackref = this;
#ifdef Y_CONFIG_FEATURE_THREADING
	newConn->is_treaded = is_threading;
#else
	newConn->is_treaded = false;
#endif
	int index = -1;
#ifdef Y_CONFIG_FEATURE_THREADING
	if(is_threading)
	{
		pthread_mutex_lock( &mutex );
		// look for free Thread slot
		for(int i=0;i<HTTPD_MAX_CONNECTIONS;i++)
		if(Connection_Thread_List[i] == (pthread_t)NULL)
		{
			index = i;
			break;
		}
		if(index == -1)
		{
			dperror("Maximum Connection-Threads reached\n");
			pthread_mutex_unlock( &mutex );
			return false;
		}
		newConn->thread_number = index; //remember Index of Thread slot (for clean up)

		// Create an orphan Thread. It is not joinable anymore
		pthread_mutex_unlock( &mutex );

		// start connection Thread
		if(pthread_create(&Connection_Thread_List[index], &attr, WebThread, (void *)newConn) != 0)
			dperror("Could not create Connection-Thread\n");
	}
	else // non threaded
#endif
	WebThread((void *) newConn);
	return ((index != -1) || !is_threading);
}
Пример #3
0
//-------------------------------------------------------------------------
int CWebserverRequest::OpenFile(string path, string filename)
{
	struct stat statbuf;
//tmpint als file und
//tmpstring als pathfilename missbraucht
	tmpint = -1;
	if(path[path.length()-1] != '/')
		tmpstring = path + "/" + filename;
	else
		tmpstring = path + filename;
	if(tmpstring.length() > 0)
	{
		tmpint = open( tmpstring.c_str(), O_RDONLY );
		if (tmpint<=0)
		{
			aprintf("cannot open file %s\n", tmpstring.c_str());
			dperror("");
		}
		fstat(tmpint,&statbuf);
		if (!S_ISREG(statbuf.st_mode)) {
			close(tmpint);
			tmpint = -1;
		}
	}
	return tmpint;
}
Пример #4
0
//-----------------------------------------------------------------------------
// Set Re-Use Option for Address.
//-----------------------------------------------------------------------------
void CySocket::set_reuse_addr()
{
#ifdef SO_REUSEADDR
	if(!set_option(SOL_SOCKET, SO_REUSEADDR))
		dperror("setsockopt(SO_REUSEADDR)\n");
#endif
}
Пример #5
0
//-----------------------------------------------------------------------------
// Set Re-Use Option for Port.
//-----------------------------------------------------------------------------
void CySocket::set_reuse_port()
{
#ifdef SO_REUSEPORT
	if(!set_option(SOL_SOCKET, SO_REUSEPORT))
		dperror("setsockopt(SO_REUSEPORT)\n");
#endif
}
Пример #6
0
//-----------------------------------------------------------------------------
// Set Keep-Alive Option for Socket.
//-----------------------------------------------------------------------------
void CySocket::set_keep_alive()
{
#ifdef SO_KEEPALIVE
	if(!set_option(SOL_SOCKET, SO_KEEPALIVE))
		dperror("setsockopt(SO_KEEPALIVE)\n");
#endif
}
Пример #7
0
//-----------------------------------------------------------------------------
// Set Keep-Alive Option for Socket.
//-----------------------------------------------------------------------------
void CySocket::set_tcp_nodelay()
{
#ifdef TCP_NODELAY
	if(!set_option(IPPROTO_TCP, TCP_NODELAY))
		dperror("setsockopt(SO_KEEPALIVE)\n");
#endif
}
//=============================================================================
// SocketList Handler
//=============================================================================
//-----------------------------------------------------------------------------
// Accept new Connection
//-----------------------------------------------------------------------------
int CWebserver::AcceptNewConnectionSocket() {
	int slot = -1;
	CySocket *connectionSock = NULL;

	if (!(connectionSock = listenSocket.accept())) // Blocking wait
	{
		dperror("Socket accept error. Continue.\n");
		delete connectionSock;
		return -1;
	}
#ifdef Y_CONFIG_USE_OPEN_SSL
	if(Cyhttpd::ConfigList["SSL"]=="true")
	connectionSock->initAsSSL(); // make it a SSL-socket
#endif
	log_level_printf(2, "FD: new con fd:%d on port:%d\n",
			connectionSock->get_socket(), connectionSock->get_accept_port());

	// Add Socket to List
	slot = SL_GetFreeSlot();
	if (slot < 0) {
		connectionSock->close();
		aprintf("No free Slot in SocketList found. Open:%d\n", open_connections);
	} else {
		SocketList[slot] = connectionSock; // put it to list
		fcntl(connectionSock->get_socket(), F_SETFD, O_NONBLOCK); // set non-blocking
		open_connections++; // count open connectins
		int newfd = connectionSock->get_socket();
		if (newfd > fdmax) // keep track of the maximum fd
			fdmax = newfd;
	}
	return slot;
}
Пример #9
0
// Frees memory allocated with ecg_alloc_buf
int ecg_free_buf(uint8_t *buffer, size_t size) {
#ifdef _MSC_VER
  if (HeapFree(ecg_hheap, 0, buffer) == 0)
    return -1;
#endif

#ifdef _POSIX_SOURCE
  if (munmap(buffer, size) != 0) {
    dperror("munmap");
    return -1;
  }
#endif

  return 0;
}
Пример #10
0
//-----------------------------------------------------------------------------
// Send File: Open File and check file type
//-----------------------------------------------------------------------------
int CmodSendfile::OpenFile(CyhookHandler */*hh*/, std::string fullfilename)
{
	int  fd= -1;
	std::string tmpstring;
	if (!fullfilename.empty())
	{
		fd = open( fullfilename.c_str(), O_RDONLY );
		if (fd<=0)
		{
			aprintf("cannot open file %s: ", fullfilename.c_str());
			dperror("");
		}
	}
	return fd;
}
Пример #11
0
bool
save_preferences (void)
{
  FILE* fs;

  dmsg (D_MISC, "save preferences to %s", preferences_file ());
  fs = fopen (preferences_file (), "wt");
  if (fs == 0) {
     wmsg ("cannot save preferences to %s", preferences_file ());
     dperror ("fopen");
     return true;
  }
  output_preferences (fs);
  fclose (fs);
  return false;
}
Пример #12
0
static int getcurtime (struct timeval *tvp)
{
#ifdef _WIN32
    struct _timeb tb;
    _ftime(&tb);
    tvp->tv_sec = tb.time;
    tvp->tv_usec = tb.millitm * 1000;
    /* Can _ftime fail?  */
    return 0;
#else
    if (gettimeofday(tvp, 0)) {
	dperror("gettimeofday");
	return errno;
    }
    return 0;
#endif
}
Пример #13
0
/* Return 0 if we sent something, non-0 otherwise.
   If 0 is returned, the caller should delay waiting for a response.
   Otherwise, the caller should immediately move on to process the
   next connection.  */
static int
maybe_send(krb5_context context, struct conn_state *conn,
           struct select_state *selstate,
           struct sendto_callback_info *callback_info)
{
    sg_buf *sg;
    ssize_t ret;

    dprint("maybe_send(@%p) state=%s type=%s\n", conn,
           state_strings[conn->state],
           conn->is_udp ? "udp" : "tcp");
    if (conn->state == INITIALIZING)
        return start_connection(context, conn, selstate, callback_info);

    /* Did we already shut down this channel?  */
    if (conn->state == FAILED) {
        dprint("connection already closed\n");
        return -1;
    }

    if (conn->socktype == SOCK_STREAM) {
        dprint("skipping stream socket\n");
        /* The select callback will handle flushing any data we
           haven't written yet, and we only write it once.  */
        return -1;
    }

    /* UDP - retransmit after a previous attempt timed out. */
    sg = &conn->x.out.sgbuf[0];
    TRACE_SENDTO_KDC_UDP_SEND_RETRY(context, conn);
    dprint("sending %d bytes on fd %d\n", SG_LEN(sg), conn->fd);
    ret = send(conn->fd, SG_BUF(sg), SG_LEN(sg), 0);
    if (ret < 0 || (size_t) ret != SG_LEN(sg)) {
        TRACE_SENDTO_KDC_UDP_ERROR_SEND_RETRY(context, conn, SOCKET_ERRNO);
        dperror("send");
        /* Keep connection alive, we'll try again next pass.

           Is this likely to catch any errors we didn't get from the
           select callbacks?  */
        return -1;
    }
    /* Yay, it worked.  */
    return 0;
}
Пример #14
0
static void
read_level_dir (const char *dirname)
{
  DIR *dir;
  struct dirent* de;
  int n = 0;

  dmsg (D_FILE | D_SECTION, "reading level list from %s", dirname);

  dir = opendir (dirname);
  if (!dir) {
    dperror ("opendir");
    emsg (_("cannot open directory %s"), dirname);
  }

  while ((de = readdir (dir)))
    if (select_file_lvl (de)) {
      char *filename;
      a_level tmp_lvl;

      if (level_list_size >= level_list_max) {
	level_list_max += 32;
	XREALLOC_ARRAY (level_list, level_list_max);
      }

      filename = xmalloc (strlen (dirname) + 1 + strlen (de->d_name) + 1);
      sprintf (filename, "%s/%s", dirname, de->d_name);
      level_list[level_list_size].name = filename;

      dmsg (D_FILE, "loading header from %s", filename);
      lvl_load_file (filename, &tmp_lvl, false);
      level_list[level_list_size].wrapped =
	(tmp_lvl.tile_width_wrap != DONT_WRAP
	 && tmp_lvl.tile_height_wrap != DONT_WRAP);
      lvl_free (&tmp_lvl);

      ++level_list_size;
    }

  closedir (dir);
  dmsg (D_FILE, "... %d files", n);
}
Пример #15
0
//-----------------------------------------------------------------------------
CySocket* CySocket::accept() {
	init();
	SOCKET newSock = ::accept(sock, (sockaddr *) &addr, &addr_len);
	if (newSock == INVALID_SOCKET) {
		dperror("accept: invalid socket\n");
		return NULL;
	}
	CySocket *new_ySocket = new CySocket(newSock);
	if (new_ySocket != NULL) {
		new_ySocket->setAddr(addr);
#ifdef TCP_CORK
		new_ySocket->set_option(IPPROTO_TCP, TCP_CORK);
#else
		set_tcp_nodelay();
#endif
	}
	new_ySocket->isOpened = true;
	//	handling = true;
	return new_ySocket;
}
Пример #16
0
// Allocates an executable buffer on the heap.
size_t ecg_alloc_buf(uint8_t **buffer, size_t size) {
#ifdef _MSC_VER
  *buffer = (uint8_t*) HeapAlloc(ecg_hheap, 0, size);
#endif

#ifdef _POSIX_SOURCE
  int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
  int flags = MAP_SHARED;

  // Allocate full pages only since we're going
  // to allocate pages at page boundaries anyways.
  size = (size + ecg_page_size) & ~(ecg_page_size - 1);
  *buffer = (uint8_t*) mmap(NULL, size, prot,
    flags, ecg_zero_page, 0);

  if (*buffer == MAP_FAILED) {
    dperror("mmap");
    return 0;
  }
#endif

  return size;
}
Пример #17
0
int CWebserverRequest::OpenFile(std::string path, std::string filename)
{
	struct stat statbuf;
	int  fd= -1;

	tmpstring = GetFileName(path, filename);

	if(tmpstring.length() > 0)
	{
		fd = open( tmpstring.c_str(), O_RDONLY );
		if (fd<=0)
		{
			aprintf("cannot open file %s: ", filename.c_str());
			dperror("");
		}
		fstat(fd,&statbuf);
		if (!S_ISREG(statbuf.st_mode)) {
			close(fd);
			fd = -1;
		}
	}
	return fd;
}
Пример #18
0
static int
start_connection(krb5_context context, struct conn_state *state,
                 struct select_state *selstate,
                 struct sendto_callback_info *callback_info)
{
    int fd, e;

    dprint("start_connection(@%p)\ngetting %s socket in family %d...", state,
           state->socktype == SOCK_STREAM ? "stream" : "dgram", state->family);
    fd = socket(state->family, state->socktype, 0);
    if (fd == INVALID_SOCKET) {
        state->err = SOCKET_ERRNO;
        dprint("socket: %m creating with af %d\n", state->err, state->family);
        return -1;              /* try other hosts */
    }
#ifndef _WIN32 /* On Windows FD_SETSIZE is a count, not a max value.  */
    if (fd >= FD_SETSIZE) {
        closesocket(fd);
        state->err = EMFILE;
        dprint("socket: fd %d too high\n", fd);
        return -1;
    }
#endif
    set_cloexec_fd(fd);
    /* Make it non-blocking.  */
    if (state->socktype == SOCK_STREAM) {
        static const int one = 1;
        static const struct linger lopt = { 0, 0 };

        if (ioctlsocket(fd, FIONBIO, (const void *) &one))
            dperror("sendto_kdc: ioctl(FIONBIO)");
        if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &lopt, sizeof(lopt)))
            dperror("sendto_kdc: setsockopt(SO_LINGER)");
        TRACE_SENDTO_KDC_TCP_CONNECT(context, state);
    }

    /* Start connecting to KDC.  */
    e = connect(fd, (struct sockaddr *)&state->addr, state->addrlen);
    if (e != 0) {
        /*
         * This is the path that should be followed for non-blocking
         * connections.
         */
        if (SOCKET_ERRNO == EINPROGRESS || SOCKET_ERRNO == EWOULDBLOCK) {
            state->state = CONNECTING;
            state->fd = fd;
        } else {
            dprint("connect failed: %m\n", SOCKET_ERRNO);
            (void) closesocket(fd);
            state->err = SOCKET_ERRNO;
            state->state = FAILED;
            return -2;
        }
    } else {
        /*
         * Connect returned zero even though we made it non-blocking.  This
         * happens normally for UDP sockets, and can perhaps also happen for
         * TCP sockets connecting to localhost.
         */
        state->state = WRITING;
        state->fd = fd;
    }
    dprint("new state = %s\n", state_strings[state->state]);


    /*
     * Here's where KPASSWD callback gets the socket information it needs for
     * a kpasswd request
     */
    if (callback_info) {

        e = callback_info->pfn_callback(state, callback_info->context,
                                        &state->callback_buffer);
        if (e != 0) {
            dprint("callback failed: %m\n", e);
            (void) closesocket(fd);
            state->err = e;
            state->fd = INVALID_SOCKET;
            state->state = FAILED;
            return -3;
        }

        set_conn_state_msg_length(state, &state->callback_buffer);
    }

    if (state->socktype == SOCK_DGRAM) {
        /* Send it now.  */
        ssize_t ret;
        sg_buf *sg = &state->x.out.sgbuf[0];

        TRACE_SENDTO_KDC_UDP_SEND_INITIAL(context, state);
        dprint("sending %d bytes on fd %d\n", SG_LEN(sg), state->fd);
        ret = send(state->fd, SG_BUF(sg), SG_LEN(sg), 0);
        if (ret < 0 || (size_t) ret != SG_LEN(sg)) {
            TRACE_SENDTO_KDC_UDP_ERROR_SEND_INITIAL(context, state,
                                                    SOCKET_ERRNO);
            dperror("sendto");
            (void) closesocket(state->fd);
            state->fd = INVALID_SOCKET;
            state->state = FAILED;
            return -4;
        } else {
            state->state = READING;
        }
    }
    FD_SET(state->fd, &selstate->rfds);
    if (state->state == CONNECTING || state->state == WRITING)
        FD_SET(state->fd, &selstate->wfds);
    FD_SET(state->fd, &selstate->xfds);
    if (selstate->max <= state->fd)
        selstate->max = state->fd + 1;
    selstate->nfds++;

    dprint("new select vectors: %F\n",
           &selstate->rfds, &selstate->wfds, &selstate->xfds, selstate->max);

    return 0;
}
Пример #19
0
//-----------------------------------------------------------------------------
// POST multipart ! FILE UPLOAD!
//
// No 'Content-type: multipart/mixed' now supported
// designed for recursion for different boundaries.
//
// 	from RFC 1867:
//	2.  HTML forms with file submission
//
//	   The current HTML specification defines eight possible values for the
//	   attribute TYPE of an INPUT element: CHECKBOX, HIDDEN, IMAGE,
//	   PASSWORD, RADIO, RESET, SUBMIT, TEXT.
//
//	   In addition, it defines the default ENCTYPE attribute of the FORM
//	   element using the POST METHOD to have the default value
//	   "application/x-www-form-urlencoded"
//
//	6. Examples
//
//	   Suppose the server supplies the following HTML:
//
//	     <FORM ACTION="http://server.dom/cgi/handle"
//	           ENCTYPE="multipart/form-data"
//	           METHOD=POST>
//	     What is your name? <INPUT TYPE=TEXT NAME=submitter>
//	     What files are you sending? <INPUT TYPE=FILE NAME=pics>
//	     </FORM>
//
//	   and the user types "Joe Blow" in the name field, and selects a text
//	   file "file1.txt" for the answer to 'What files are you sending?'
//
//	   The client might send back the following data:
//
//	        Content-type: multipart/form-data, boundary=AaB03x
//
//	        --AaB03x
//	        content-disposition: form-data; name="field1"
//
//	        Joe Blow
//	        --AaB03x
//	        content-disposition: form-data; name="pics"; filename="file1.txt"
//	        Content-Type: text/plain
//
//	         ... contents of file1.txt ...
//	        --AaB03x--
//
//	7. Registration of multipart/form-data
//
//	   The media-type multipart/form-data follows the rules of all multipart
//	   MIME data streams as outlined in RFC 1521. It is intended for use in
//	   returning the data that comes about from filling out a form. In a
//	   form (in HTML, although other applications may also use forms), there
//	   are a series of fields to be supplied by the user who fills out the
//	   form. Each field has a name. Within a given form, the names are
//	   unique.
//
//	   multipart/form-data contains a series of parts. Each part is expected
//	   to contain a content-disposition header where the value is "form-
//	   data" and a name attribute specifies the field name within the form,
//	   e.g., 'content-disposition: form-data; name="xxxxx"', where xxxxx is
//	   the field name corresponding to that field. Field names originally in
//	   non-ASCII character sets may be encoded using the method outlined in
//	   RFC 1522.
//
//	   As with all multipart MIME types, each part has an optional Content-
//	   Type which defaults to text/plain.  If the contents of a file are
//	   returned via filling out a form, then the file input is identified as
//	   application/octet-stream or the appropriate media type, if known.  If
//	   multiple files are to be returned as the result of a single form
//	   entry, they can be returned as multipart/mixed embedded within the
//	   multipart/form-data.
//
//	   Each part may be encoded and the "content-transfer-encoding" header
//	   supplied if the value of that part does not conform to the default
//	   encoding.
//
//	   File inputs may also identify the file name. The file name may be
//	   described using the 'filename' parameter of the "content-disposition"
//	   header. This is not required, but is strongly recommended in any case
//	   where the original filename is known. This is useful or necessary in
//	   many applications.
//-----------------------------------------------------------------------------
unsigned int CWebserverRequest::HandlePostBoundary(std::string boundary, unsigned int content_len)
{
	std::string tmp_line;

	// read boundary
	tmp_line = Connection->sock->ReceiveLine();
	content_len -= tmp_line.length();

	log_level_printf(2,"<POST Boundary> Start\n");
	if(tmp_line.find(boundary) != std::string::npos)
	{
		// is it the boudary end?
		if(tmp_line.find(boundary+"--") != std::string::npos)
		{
			log_level_printf(7,"<POST Boundary> Boundary END found\n");
			return 0;
		}
		log_level_printf(7,"<POST Boundary> Boundary START found\n");

		// read content-disposition: ...
		tmp_line = Connection->sock->ReceiveLine();
		content_len -= tmp_line.length();
		if(tmp_line.find("Content-Disposition:") == std::string::npos)
		{
			log_level_printf(7,"<POST Boundary> no content-disposition found. line:(%s)\n", tmp_line.c_str());
			return 0;
		}
		if(tmp_line.find("filename") != std::string::npos)
		{
#ifdef Y_CONFIG_FEATURE_UPLOAD
			// this part is a file
			log_level_printf(2,"<POST Boundary> disposition !!this is a file!! found. line:(%s)\n", tmp_line.c_str());
			// get para from 'content-disposition: form-data; name="pics"; filename="file1.txt"'
			// set to ParameterList["<name>"]="<filename>"
			std::string left, right, var_name, var_value;
			if(!ySplitStringExact(tmp_line, "name=\"", left, right))
			{
				log_level_printf(7,"<POST Boundary> no var_name START found. line:(%s)\n", tmp_line.c_str());
				return 0;
			}
			if(!ySplitStringExact(right, "\"", var_name, right))
			{
				log_level_printf(7,"<POST Boundary> no var_name END found. line:(%s)\n", tmp_line.c_str());
				return 0;
			}
			if(!ySplitStringExact(right, "filename=\"", left, right))
			{
				log_level_printf(7,"<POST Boundary> no filename START found. line:(%s)\n", tmp_line.c_str());
				return 0;
			}
			if(!ySplitStringExact(right, "\"", var_value, right))
			{
				log_level_printf(7,"<POST Boundary> no filename END found. line:(%s)\n", tmp_line.c_str());
				return 0;
			}
			var_value = trim(var_value);
			ParameterList[var_name] = var_value;
			log_level_printf(7,"<POST Boundary> filename found. name:(%s) value:(%s)\n", var_name.c_str(), var_value.c_str());

			//read 'Content-Type: <mime>'
			tmp_line = Connection->sock->ReceiveLine();
			content_len -= tmp_line.length();
			// Get Content-Type: put it to ParameterList["<name>_mime"]="<mime>"
			if(!ySplitStringExact(tmp_line, "Content-Type:", left, right))
			{
				log_level_printf(7,"<POST Boundary> no Content-Type found. line:(%s)\n", tmp_line.c_str());
				return 0;
			}
			var_value = trim(right);
			ParameterList[var_name+"_mime"] = var_value;
			log_level_printf(7,"<POST Boundary> Content-Type found. name:(%s_mime) value:(%s)\n", var_name.c_str(), var_value.c_str());


			//read empty line as separator
			tmp_line = Connection->sock->ReceiveLine();
			content_len -= tmp_line.length();
			if(tmp_line != "\r\n")
			{
				log_level_printf(7,"<POST Boundary> no empty line found. line:(%s)\n", tmp_line.c_str());
				return 0;

			}
			log_level_printf(7,"<POST Boundary> read file Start\n");

			std::string upload_filename;
			upload_filename = UPLOAD_TMP_FILE;
			// Hook for Filename naming
			Connection->HookHandler.Hooks_UploadSetFilename(upload_filename);
			// Set upload filename to ParameterList["<name>_upload_filename"]="<upload_filename>"
			ParameterList[var_name+"_upload_filename"] = upload_filename;

			// open file for write
			int fd = open(upload_filename.c_str(), O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
			if (fd<=0)
			{
				aprintf("cannot open file %s: ", upload_filename.c_str());
				dperror("");
				return 0;
			}

			// ASSUMPTION: the complete multipart has no more then SEARCH_BOUNDARY_LEN bytes after the file.
			// It only works, if no multipart/mixed is used (e.g. in file attachments). Not nessesary in embedded systems.
			// To speed up uploading, read content_len - SEARCH_BOUNDARY_LEN bytes in blockmode.
			// To save memory, write them direct into the file.
			#define SEARCH_BOUNDARY_LEN 2*RECEIVE_BLOCK_LEN // >= RECEIVE_BLOCK_LEN in ySocket
			unsigned int _readbytes = 0;
			if((int)content_len - SEARCH_BOUNDARY_LEN >0)
			{
				_readbytes = Connection->sock->ReceiveFileGivenLength(fd, content_len - SEARCH_BOUNDARY_LEN);
				content_len -= _readbytes;
				log_level_printf(8,"<POST Boundary> read block (already:%d all:%d)\n", _readbytes, content_len);
			}

			// read rest of file and check for boundary end
			_readbytes = 0;
			bool is_CRLF = false;

			bool found_end_boundary = false;
			do
			{
				// read line by line
				tmp_line = Connection->sock->ReceiveLine();
				_readbytes += tmp_line.length();

				// is this line a boundary?
				if(tmp_line.find(boundary) != std::string::npos)
				{
					if(tmp_line.find(boundary+"--") != std::string::npos)
						found_end_boundary = true; // it is the end! of POST request!
					break;	// boundary found. end of file.
				}
				else // no Boundary: write CRFL if found in last line
				{
					if(is_CRLF)
				    		if ((unsigned int)write(fd, "\r\n", 2) != 2)
				    		{
							perror("write file failed\n");
				      			return 0;
				      		}
				}
				// normal line: write it to file
				// CRLF at end? Maybe CRLF before boundary. Can not decide yet
				is_CRLF = (tmp_line.length()>=2 && tmp_line[tmp_line.length()-2]=='\r' && tmp_line[tmp_line.length()-1]=='\n');
				int write_len = is_CRLF ? tmp_line.length()-2 : tmp_line.length();
		    		if (write(fd, tmp_line.c_str(), write_len) != write_len)
		    		{
					perror("write file failed\n");
		      			return 0;
		      		}
				log_level_printf(2,"<POST Boundary> read file (already:%d all:%d)\n", _readbytes, content_len);
			}
			while((_readbytes < content_len) && (tmp_line.length() != 0));
			content_len -= _readbytes;
			close(fd);
			log_level_printf(2,"<POST Boundary> read file End\n");
			if(found_end_boundary) // upload ok?
			{

				Connection->HookHandler.Hooks_UploadReady(upload_filename);
				return 0;
			}
#endif // Y_CONFIG_FEATURE_UPLOAD
		}
		else
		// this part is a POST variable/parameter
		{
			// get var_name from 'content-disposition: form-data; name="var_name"'
			std::string left, right, var_name, var_value;
			if(!ySplitStringExact(tmp_line, "name=\"", left, right))
			{
				log_level_printf(7,"<POST Boundary> no var_name START found. line:(%s)\n", tmp_line.c_str());
				return 0;
			}
			if(!ySplitStringExact(right, "\"", var_name, right))
			{
				log_level_printf(7,"<POST Boundary> no var_name END found. line:(%s)\n", tmp_line.c_str());
				return 0;
			}

			//read empty line as separator
			tmp_line = Connection->sock->ReceiveLine();
			content_len -= tmp_line.length();
			if(tmp_line != "\r\n")
			{
				log_level_printf(7,"<POST Boundary> no empty line found. line:(%s)\n", tmp_line.c_str());
				return 0;

			}
			//read var_value line
			// ASSUMPTION!!!! Only one Line for value, new line is a boundary again
			// ATTENTION!! var_name must not be unique. So Parameters are store by number too.
			var_value = Connection->sock->ReceiveLine();
			content_len -= tmp_line.length();
			var_value = trim(decodeString(var_value));
			ParameterList[var_name] = var_value;
			log_level_printf(7,"<POST Boundary> Parameter found. name:(%s) value:(%s)\n", var_name.c_str(), var_value.c_str());
		}
	}
	return content_len;
}
Пример #20
0
bool
load_preferences (void)
{
  FILE* fs;
  int endline = 0;
  char* buf = 0;
  size_t bufsize = 0;

  firstline = 0;

  reinit_preferences ();

  dmsg (D_FILE, "reading option from %s", preferences_file ());
  fs = fopen (preferences_file (), "rb");

  if (fs == NULL) {
    /* Don't warn, the file doesn't exists the first time.  */
    dmsg (D_FILE, "cannot open preferences file %s", preferences_file ());
    dperror ("fopen");
    return true;
  }

  XFREE0 (ignored_lines);

  while (getshline_numbered
	 (&firstline, &endline, &buf, &bufsize, fs) != -1) {
    char* token;
    char* line = xstrdup (buf);

    token = strtok (buf, " \t.:");
    if (!strcasecmp ("heroes", token)) {
    token = strtok (0, " \t.:");
    if (!strcasecmp ("screen", token)) {
    token = strtok (0, " \t.:");
    if (!strcasecmp ("display_radar", token)) {
    token = strtok (0, "\n");
    opt.radar_map = parse_bool (token, false, true);
    } else 
    if (!strcasecmp ("display_infos", token)) {
    token = strtok (0, "\n");
    opt.display_infos = parse_bool (token, false, true);
    } else 
    if (!strcasecmp ("gamma", token)) {
    token = strtok (0, "\n");
    opt.luminance = parse_unsigned (token, 0, 12);
    } else 
    if (!strcasecmp ("inertia", token)) {
    token = strtok (0, "\n");
    opt.inertia = parse_bool (token, false, true);
    } else { append_ignored (line); }
    } else 
    if (!strcasecmp ("sound", token)) {
    token = strtok (0, " \t.:");
    if (!strcasecmp ("music_enable", token)) {
    token = strtok (0, "\n");
    opt.music = parse_bool (token, false, true);
    } else 
    if (!strcasecmp ("music_volume", token)) {
    token = strtok (0, "\n");
    opt.music_volume = parse_unsigned (token, 0, 12);
    } else 
    if (!strcasecmp ("sfx_enable", token)) {
    token = strtok (0, "\n");
    opt.sfx = parse_bool (token, false, true);
    } else 
    if (!strcasecmp ("sfx_volume", token)) {
    token = strtok (0, "\n");
    opt.sfx_volume = parse_unsigned (token, 0, 12);
    } else { append_ignored (line); }
    } else 
    if (!strcasecmp ("control", token)) {
    token = strtok (0, " \t.:");
    if (!strcasecmp ("player1", token)) {
    token = strtok (0, "\n");
    opt.ctrl_one = parse_unsigned (token, 0, 1);
    } else 
    if (!strcasecmp ("autopilot1", token)) {
    token = strtok (0, "\n");
    opt.autopilot_one = parse_bool (token, false, true);
    } else 
    if (!strcasecmp ("player2", token)) {
    token = strtok (0, "\n");
    opt.ctrl_two = parse_unsigned (token, 0, 1);
    } else 
    if (!strcasecmp ("autopilot2", token)) {
    token = strtok (0, "\n");
    opt.autopilot_two = parse_bool (token, false, true);
    } else { append_ignored (line); }
    } else 
    if (!strcasecmp ("game", token)) {
    token = strtok (0, " \t.:");
    if (!strcasecmp ("speed", token)) {
    token = strtok (0, "\n");
    opt.speed = parse_unsigned (token, 0, 2);
    } else 
    if (!strcasecmp ("gamerounds", token)) {
    token = strtok (0, "\n");
    opt.gamerounds = parse_unsigned (token, 0, 15);
    } else 
    if (!strcasecmp ("player_colors", token)) {
    token = strtok (0, " \t");
    opt.player_color[0] = parse_unsigned (token, 0, 4);
    token = strtok (0, " \t");
    opt.player_color[1] = parse_unsigned (token, 0, 4);
    token = strtok (0, " \t");
    opt.player_color[2] = parse_unsigned (token, 0, 4);
    token = strtok (0, " \t");
    opt.player_color[3] = parse_unsigned (token, 0, 4);
    } else { append_ignored (line); }
    } else 
    if (!strcasecmp ("extras", token)) {
    token = strtok (0, " \t.:");
    if (!strcasecmp ("mode", token)) {
    token = strtok (0, "\n");
    opt.extras = parse_unsigned (token, 0, 2);
    } else { append_ignored (line); }
    } else 
    if (!strcasecmp (keys_pref_group (), token)) {
    token = strtok (0, " \t.:");
    if (!strcasecmp ("player1_keys", token)) {
    token = strtok (0, " \t");
    opt.player_keys[0][0] = parse_unsigned (token, 0, HKEYCODE_MAX);
    token = strtok (0, " \t");
    opt.player_keys[0][1] = parse_unsigned (token, 0, HKEYCODE_MAX);
    token = strtok (0, " \t");
    opt.player_keys[0][2] = parse_unsigned (token, 0, HKEYCODE_MAX);
    token = strtok (0, " \t");
    opt.player_keys[0][3] = parse_unsigned (token, 0, HKEYCODE_MAX);
    token = strtok (0, " \t");
    opt.player_keys[0][4] = parse_unsigned (token, 0, HKEYCODE_MAX);
    token = strtok (0, " \t");
    opt.player_keys[0][5] = parse_unsigned (token, 0, HKEYCODE_MAX);
    } else 
    if (!strcasecmp ("player2_keys", token)) {
    token = strtok (0, " \t");
    opt.player_keys[1][0] = parse_unsigned (token, 0, HKEYCODE_MAX);
    token = strtok (0, " \t");
    opt.player_keys[1][1] = parse_unsigned (token, 0, HKEYCODE_MAX);
    token = strtok (0, " \t");
    opt.player_keys[1][2] = parse_unsigned (token, 0, HKEYCODE_MAX);
    token = strtok (0, " \t");
    opt.player_keys[1][3] = parse_unsigned (token, 0, HKEYCODE_MAX);
    token = strtok (0, " \t");
    opt.player_keys[1][4] = parse_unsigned (token, 0, HKEYCODE_MAX);
    token = strtok (0, " \t");
    opt.player_keys[1][5] = parse_unsigned (token, 0, HKEYCODE_MAX);
    } else { append_ignored (line); }
    } else { append_ignored (line); }
    } else { append_ignored (line); }
    free (line);
  }

  free (buf);
  fclose (fs);
  return false;
}
Пример #21
0
int main(int argc, char **argv)
{
	aprintf("Webserver %s\n", WEBSERVERNAME);
	bool do_fork = true;
	yhttpd = new Cyhttpd();
	if(!yhttpd)
	{
		aprintf("Error initializing WebServer\n");
		return EXIT_FAILURE;
	}
	for (int i = 1; i < argc; i++)
	{
		if ((!strncmp(argv[i], "-d", 2)) || (!strncmp(argv[i], "--debug", 7)))
		{
			CLogging::getInstance()->setDebug(true);
			do_fork = false;
		}
		else if ((!strncmp(argv[i], "-f", 2)) || (!strncmp(argv[i], "--fork", 6)))
		{
			do_fork = false;
		}
		else if ((!strncmp(argv[i], "-h", 2)) || (!strncmp(argv[i], "--help", 6)))
		{
			yhttpd->usage(stdout);
			return EXIT_SUCCESS;
		}
		else if ((!strncmp(argv[i], "-v", 2)) || (!strncmp(argv[i],"--version", 9)))
		{
			yhttpd->version(stdout);
			return EXIT_SUCCESS;
		}
		else if ((!strncmp(argv[i], "-t", 2)) || (!strncmp(argv[i],"--thread-off", 12)))
		{
			yhttpd->flag_threading_off = true;
		}
		else if ((!strncmp(argv[i], "-l", 2)) )
		{
			if(argv[i][2] >= '0' && argv[i][2] <= '9')
			CLogging::getInstance()->LogLevel = (argv[i][2]-'0');
		}
		else
		{
			yhttpd->usage(stderr);
			return EXIT_FAILURE;
		}
	}
	// setup signal catching (subscribing)
	signal(SIGPIPE, sig_catch);
	signal(SIGINT, sig_catch);
	signal(SIGHUP, sig_catch);
	signal(SIGUSR1, sig_catch);
	signal(SIGTERM, sig_catch);
	signal(SIGCLD, SIG_IGN);
	//	signal(SIGALRM, sig_catch);

	yhttpd->hooks_attach();
	yhttpd->ReadConfig();
	if(yhttpd->Configure())
	{
		// Start Webserver: fork ist if not in debug mode
		aprintf("Webserver starting...\n");
		if (do_fork)
		{
			log_level_printf(9,"do fork\n");
			switch (fork()) {
				case -1:
				dperror("fork");
				return -1;
				case 0:
				break;
				default:
				return EXIT_SUCCESS;
			}

			if (setsid() == -1)
			{
				dperror("Error setsid");
				return EXIT_FAILURE;
			}
		}
		dprintf("Start in Debug-Mode\n"); // non forked debugging loop

		yhttpd->run();
	}
	delete yhttpd;

	aprintf("Main end\n");
	return EXIT_SUCCESS;
}
Пример #22
0
//-----------------------------------------------------------------------------
// Change to Root
//-----------------------------------------------------------------------------
bool Cyhttpd::Configure() {

	if (!getuid()) // you must be root to do that!
	{
		// Get user and group data
#ifdef Y_CONFIG_FEATURE_HTTPD_USER
		struct passwd *pwd = NULL;
		struct group *grp = NULL;
		std::string username = ConfigList["server.user_name"];
		std::string groupname= ConfigList["server.group_name"];

		// get user data
		if(!username.empty())
		{
			if((pwd = getpwnam(username.c_str())) == NULL)
			{
				dperror("Dont know user to set uid\n");
				return false;
			}
		}
		// get group data
		if(!groupname.empty())
		{
			if((grp = getgrnam(groupname.c_str())) == NULL)
			{
				aprintf("Can not get Group-Information. Group: %s\n", groupname.c_str());
				return false;
			}
		}
#endif
		// change root directory
#ifdef Y_CONFIG_FEATURE_CHROOT
		if(!ConfigList["server.chroot"].empty())
		{
			log_level_printf(2, "do chroot to dir:%s\n", ConfigList["server.chroot"].c_str() );
			// do change Root
			if(chroot(ConfigList["server.chroot"].c_str()) == -1)
			{
				dperror("Change Root failed\n");
				return false;
			}
			// Set Working Dir
			if(chdir("/") == -1)
			{
				dperror("Change Directory to Root failed\n");
				return false;
			}
		}
#endif
#ifdef Y_CONFIG_FEATURE_HTTPD_USER
		if(!username.empty() && pwd != NULL && grp != NULL)
		{
			log_level_printf(2, "set user and groups\n");

			// drop root privileges
			setgid(grp->gr_gid);
			setgroups(0, NULL);
			// set user group
			if(!groupname.empty())
			initgroups(username.c_str(), grp->gr_gid);
			// set user
			if(setuid(pwd->pw_uid) == -1)
			{
				dperror("Change User Context failed\n");
				return false;
			}
		}
#endif
	}
	return true;
}
Пример #23
0
void parse_command(int connfd, CBasicMessage::Header * rmessage)
{

	if(rmessage->version!=CTimerd::ACTVERSION)
	{
		dperror("command with unknown version\n");
		return;
	}

//	CTimerEvent_NextProgram::EventMap::iterator it = NULL;
	CTimerEventMap events;
	CTimerd::commandModifyTimer msgModifyTimer;
	CTimerd::responseGetSleeptimer rspGetSleeptimer;
	CTimerEventMap::iterator pos;
	switch(rmessage->cmd)
	{
		
		case CTimerd::CMD_REGISTEREVENT :
			CTimerManager::getInstance()->getEventServer()->registerEvent( connfd );
			break;

		case CTimerd::CMD_UNREGISTEREVENT :
			CTimerManager::getInstance()->getEventServer()->unRegisterEvent( connfd );
			break;

		case CTimerd::CMD_GETSLEEPTIMER:
			rspGetSleeptimer.eventID = 0;
			if(CTimerManager::getInstance()->listEvents(events))
			{
				if(events.size() > 0)
				{
					for(pos = events.begin();(pos != events.end());pos++)
					{
						printf("ID: %u type: %u\n",pos->second->eventID,pos->second->eventType);
						if(pos->second->eventType == CTimerd::TIMER_SLEEPTIMER)
						{
							rspGetSleeptimer.eventID = pos->second->eventID;
							break;
						}
					}
				}
			}
			write( connfd, &rspGetSleeptimer, sizeof(rspGetSleeptimer));
			break;

		case CTimerd::CMD_GETTIMER:						// timer daten abfragen
			CTimerd::commandGetTimer msgGetTimer;
			CTimerd::responseGetTimer resp;
			read(connfd,&msgGetTimer, sizeof(msgGetTimer));
			if(CTimerManager::getInstance()->listEvents(events))
			{
				if(events[msgGetTimer.eventID])
				{
					CTimerEvent *event = events[msgGetTimer.eventID];
					resp.eventID = event->eventID;
					resp.eventState = event->eventState;
					resp.eventType = event->eventType;
					resp.eventRepeat = event->eventRepeat;
					resp.announceTime = event->announceTime;
					resp.alarmTime = event->alarmTime;
					resp.stopTime = event->stopTime;

					if(event->eventType == CTimerd::TIMER_STANDBY)
						resp.standby_on = static_cast<CTimerEvent_Standby*>(event)->standby_on;
					else if(event->eventID == CTimerd::TIMER_NEXTPROGRAM)
					{
						resp.epgID = static_cast<CTimerEvent_NextProgram*>(event)->eventInfo.epgID;
						resp.channel_id = static_cast<CTimerEvent_NextProgram*>(event)->eventInfo.channel_id;
					}
					else if(event->eventID == CTimerd::TIMER_RECORD)
					{
						resp.epgID = static_cast<CTimerEvent_Record*>(event)->eventInfo.epgID;
						resp.channel_id = static_cast<CTimerEvent_Record*>(event)->eventInfo.channel_id;
						resp.apid = static_cast<CTimerEvent_Record*>(event)->eventInfo.apid;
					}
					else if(event->eventID == CTimerd::TIMER_ZAPTO)
					{
						resp.epgID = static_cast<CTimerEvent_Zapto*>(event)->eventInfo.epgID;
						resp.channel_id = static_cast<CTimerEvent_Zapto*>(event)->eventInfo.channel_id;
					}
					else if(event->eventID == CTimerd::TIMER_REMIND)
					{
						memset(resp.message, 0, sizeof(resp.message));
						strncpy(resp.message, static_cast<CTimerEvent_Remind*>(event)->message, sizeof(resp.message)-1);
					}
				}
			}
			write( connfd, &resp, sizeof(CTimerd::responseGetTimer));
			break;

		case CTimerd::CMD_GETTIMERLIST:				// liste aller timer 
			if(CTimerManager::getInstance()->listEvents(events))
			{
				for(CTimerEventMap::iterator pos = events.begin();pos != events.end();pos++)
				{
					CTimerd::responseGetTimer resp;

					CTimerEvent *event = pos->second;

					resp.eventID = event->eventID;
					resp.eventState = event->eventState;
					resp.eventType = event->eventType;
					resp.eventRepeat = event->eventRepeat;
					resp.announceTime = event->announceTime;
					resp.alarmTime = event->alarmTime;
					resp.stopTime = event->stopTime;
					if(event->eventType == CTimerd::TIMER_STANDBY)
						resp.standby_on = static_cast<CTimerEvent_Standby*>(event)->standby_on;
					else if(event->eventType == CTimerd::TIMER_NEXTPROGRAM)
					{
						resp.epgID = static_cast<CTimerEvent_NextProgram*>(event)->eventInfo.epgID;
						resp.channel_id = static_cast<CTimerEvent_NextProgram*>(event)->eventInfo.channel_id;
					}
					else if(event->eventType == CTimerd::TIMER_RECORD)
					{
						resp.epgID = static_cast<CTimerEvent_Record*>(event)->eventInfo.epgID;
						resp.channel_id = static_cast<CTimerEvent_Record*>(event)->eventInfo.channel_id;
						resp.apid = static_cast<CTimerEvent_Record*>(event)->eventInfo.apid;
					}
					else if(event->eventType == CTimerd::TIMER_ZAPTO)
					{
						resp.epgID = static_cast<CTimerEvent_Zapto*>(event)->eventInfo.epgID;
						resp.channel_id = static_cast<CTimerEvent_Zapto*>(event)->eventInfo.channel_id;
					}
					else if(event->eventType == CTimerd::TIMER_REMIND)
					{
						strcpy(resp.message, static_cast<CTimerEvent_Remind*>(event)->message);
					}
					write( connfd, &resp, sizeof(CTimerd::responseGetTimer));
				}
			}
			break;

		case CTimerd::CMD_RESCHEDULETIMER:			// event nach vorne oder hinten schieben
			{
				read(connfd,&msgModifyTimer, sizeof(msgModifyTimer));
				int ret=CTimerManager::getInstance()->rescheduleEvent(msgModifyTimer.eventID,msgModifyTimer.announceTime,msgModifyTimer.alarmTime, msgModifyTimer.stopTime);
				CTimerd::responseStatus rspStatus;
				rspStatus.status = (ret!=0);
				write( connfd, &rspStatus, sizeof(rspStatus));
				break;
			}

		case CTimerd::CMD_MODIFYTIMER:				// neue zeiten setzen
			{
				read(connfd,&msgModifyTimer, sizeof(msgModifyTimer));
				int ret=CTimerManager::getInstance()->modifyEvent(msgModifyTimer.eventID,msgModifyTimer.announceTime,msgModifyTimer.alarmTime, msgModifyTimer.stopTime,
																				  msgModifyTimer.eventRepeat );
				CTimerd::responseStatus rspStatus;
				rspStatus.status = (ret!=0);
				write( connfd, &rspStatus, sizeof(rspStatus));
				break;
			}

		case CTimerd::CMD_ADDTIMER:						// neuen timer hinzufügen
			CTimerd::commandAddTimer msgAddTimer;
			read(connfd,&msgAddTimer, sizeof(msgAddTimer));

			CTimerd::responseAddTimer rspAddTimer;
			CTimerEvent* event;
			CTimerd::EventInfo evInfo;
			switch(msgAddTimer.eventType)
			{
				case CTimerd::TIMER_STANDBY :
					CTimerd::commandSetStandby standby;
					read( connfd, &standby, sizeof(CTimerd::commandSetStandby));

					event = new CTimerEvent_Standby(
															 msgAddTimer.announceTime,
															 msgAddTimer.alarmTime,
															 standby.standby_on,
															 msgAddTimer.eventRepeat);
					rspAddTimer.eventID = CTimerManager::getInstance()->addEvent( event);
					break;

				case CTimerd::TIMER_SHUTDOWN :
					event = new CTimerEvent_Shutdown(
															  msgAddTimer.announceTime,
															  msgAddTimer.alarmTime,
															  msgAddTimer.eventRepeat);
					rspAddTimer.eventID = CTimerManager::getInstance()->addEvent( event);
					break;

				case CTimerd::TIMER_SLEEPTIMER :
					event = new CTimerEvent_Sleeptimer(
																 msgAddTimer.announceTime,
																 msgAddTimer.alarmTime,
																 msgAddTimer.eventRepeat);
					rspAddTimer.eventID = CTimerManager::getInstance()->addEvent( event);
					break;

				case CTimerd::TIMER_RECORD :
					read( connfd, &evInfo, sizeof(CTimerd::EventInfo));
					event = new CTimerEvent_Record(
															msgAddTimer.announceTime,
															msgAddTimer.alarmTime,
															msgAddTimer.stopTime,
															evInfo.channel_id,
															evInfo.epgID,
															evInfo.apid,
															msgAddTimer.eventRepeat);
					rspAddTimer.eventID = CTimerManager::getInstance()->addEvent( event);
					break;

				case CTimerd::TIMER_ZAPTO :
					read( connfd, &evInfo, sizeof(CTimerd::EventInfo));
					if(evInfo.channel_id > 0)
					{
						event = new CTimerEvent_Zapto(
															  msgAddTimer.announceTime,
															  msgAddTimer.alarmTime,
															  evInfo.channel_id,
															  evInfo.epgID,
															  msgAddTimer.eventRepeat);
						rspAddTimer.eventID = CTimerManager::getInstance()->addEvent( event);
					}
					break;

				case CTimerd::TIMER_NEXTPROGRAM :
//					CTimerd::EventInfo evInfo;
					read( connfd, &evInfo, sizeof(CTimerd::EventInfo));
/*
					it = CTimerEvent_NextProgram::events.find( evInfo.uniqueKey);
					if (it == CTimerEvent_NextProgram::events.end())
					{
						event = new CTimerEvent_NextProgram(
							msgAddTimer.announceTime,
							msgAddTimer.alarmTime,
							msgAddTimer.stopTime,
							msgAddTimer.eventRepeat);
						static_cast<CTimerEvent_NextProgram*>(event)->eventInfo = evInfo;
						CTimerEvent_NextProgram::events.insert(make_pair(static_cast<CTimerEvent_NextProgram*>(event)->eventInfo.uniqueKey, static_cast<CTimerEvent_NextProgram*>(event)));
						rspAddTimer.eventID = CTimerManager::getInstance()->addEvent( event);
					}
					else
					{
						event = it->second;
						static_cast<CTimerEvent_NextProgram*>(event)->eventInfo = evInfo;
						event->alarmtime.tm_mon  = msgAddTimer.month;
						event->alarmtime.tm_mday = msgAddTimer.day;
						event->alarmtime.tm_hour = msgAddTimer.hour;
						event->alarmtime.tm_min  = msgAddTimer.min;
						rspAddTimer.eventID = event->eventID;
					}
*/
					break;
				case CTimerd::TIMER_REMIND :
					CTimerd::commandRemind remind;
					read( connfd, &remind, sizeof(CTimerd::commandRemind));
					event = new CTimerEvent_Remind(msgAddTimer.announceTime,
															 msgAddTimer.alarmTime,
															 remind.message,
															 msgAddTimer.eventRepeat);
					rspAddTimer.eventID = CTimerManager::getInstance()->addEvent( event);
					break;

				default:
					printf("[timerd] Unknown TimerType\n");
			}

			write( connfd, &rspAddTimer, sizeof(rspAddTimer));

			break;
		case CTimerd::CMD_REMOVETIMER:						//	timer entfernen
			dprintf("TIMERD: command remove\n");
			CTimerd::commandRemoveTimer msgRemoveTimer;
			read(connfd,&msgRemoveTimer, sizeof(msgRemoveTimer));
			dprintf("TIMERD: command remove %d\n",msgRemoveTimer.eventID );
			CTimerManager::getInstance()->removeEvent( msgRemoveTimer.eventID);
			break;

		case CTimerd::CMD_TIMERDAVAILABLE:					// testen ob server läuft ;)
			{
				CTimerd::responseAvailable rspAvailable;
				rspAvailable.available = true;
				write( connfd, &rspAvailable, sizeof(rspAvailable));
			}
			break;
		case CTimerd::CMD_SHUTDOWN:
			{
				bool ret=CTimerManager::getInstance()->shutdown();
				CTimerd::responseStatus rspStatus;
				rspStatus.status = ret;
				write( connfd, &rspStatus, sizeof(rspStatus));
				doLoop=false;
			}
			break;
		case CTimerd::CMD_SETAPID:				  // apid setzen
			{
				CTimerd::commandSetAPid data;
				read(connfd,&data, sizeof(data));
				CTimerManager::getInstance()->modifyEvent(data.eventID , data.apid );
			}
			break;
		default:
			dprintf("unknown command\n");
	}
}
Пример #24
0
int main(int argc, char **argv)
{
	int listenfd, connfd;
	struct sockaddr_un servaddr;
	int clilen;
	bool do_fork = true;
	bool no_wait = false;
	doLoop=true;

	dprintf("startup!!!\n\n");
	if(argc > 1)
	{
		for(int i = 1; i < argc; i++)
		{

			if(strncmp(argv[i], "-f", 2) == 0)
			{
				do_fork = false;
			}
			else if(strncmp(argv[i], "-w", 2) == 0)
			{
				no_wait=true;
			}
		}
	}

	if(do_fork)
	{
		switch(fork())
		{
			case -1:
				perror("[timerd] fork");
				return -1;
			case 0:
				break;
			default:
				return 0;
		}
		if(setsid() == -1)
		{
			perror("[timerd] setsid");
			return -1;
		}
	}

	memset(&servaddr, 0, sizeof(struct sockaddr_un));
	servaddr.sun_family = AF_UNIX;
	strcpy(servaddr.sun_path, TIMERD_UDS_NAME);
	clilen = sizeof(servaddr.sun_family) + strlen(servaddr.sun_path);
	unlink(TIMERD_UDS_NAME);

	//network-setup
	if((listenfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
	{
		dperror("error while socket create");
	}

	if( bind(listenfd, (struct sockaddr*) &servaddr, clilen) <0 )
	{
		dperror("bind failed...");
		exit(-1);
	}

	if(listen(listenfd, 15) !=0)
	{
		perror("listen failed...");
		exit( -1 );
	}

	if(!no_wait)
	{
		// wait for correct date to be set...
		CSectionsdClient sectionsd;
		while(!sectionsd.getIsTimeSet())
			sleep(1);
	}
	loadTimersFromConfig();

	//startup Timer
	try
	{
		CBasicMessage::Header rmessage;
		while(doLoop)							  // wait for incomming messages
		{
			connfd = accept(listenfd, (struct sockaddr*) &servaddr, (socklen_t*) &clilen);
			memset(&rmessage, 0, sizeof(rmessage));
			read(connfd,&rmessage,sizeof(rmessage));
			parse_command(connfd, &rmessage);
			close(connfd);
		}
	}
	catch(std::exception& e)
	{
		dprintf("caught std-exception in main-thread %s!\n", e.what());
	}
	catch(...)
	{
		dprintf("caught exception in main-thread!\n");
	}
}
bool CWebserver::run(void) {
	set_threadname(__func__);
	if (!listenSocket.listen(port, HTTPD_MAX_CONNECTIONS)) {
		if (port != 80) {
			fprintf(stderr, "[yhttpd] Socket cannot bind and listen on port %d Abort.\n", port);
			return false;
		}
		fprintf(stderr, "[yhttpd] cannot bind and listen on port 80, retrying on port 8080.\n");
		port = 8080;
		if (!listenSocket.listen(port, HTTPD_MAX_CONNECTIONS)) {
			fprintf(stderr, "[yhttpd] Socket cannot bind and listen on port %d Abort.\n", port);
			return false;
		}
	}
#ifdef Y_CONFIG_FEATURE_KEEP_ALIVE

	// initialize values for select
	int listener = listenSocket.get_socket();// Open Listener
	struct timeval tv; // timeout struct
	FD_SET(listener, &master); // add the listener to the master set
	fdmax = listener; // init max fd
	fcntl(listener, F_SETFD , O_NONBLOCK); // listener master socket non-blocking
	int timeout_counter = 0; // Counter for Connection Timeout checking
	int test_counter = 0; // Counter for Testing long running Connections

	// main Webserver Loop
	while(!terminate)
	{
		// select : init vars
		read_fds = master; // copy it
		tv.tv_usec = 10000; // microsec: Timeout for select ! for re-use / keep-alive socket
		tv.tv_sec = 0; // seconds
		int fd = -1;

		// select : wait for socket activity
		if(open_connections <= 0) // No open Connection. Wait in select.
		fd = select(fdmax+1,&read_fds, NULL, NULL, NULL);// wait for socket activity
		else
		fd = select(fdmax+1,&read_fds, NULL, NULL, &tv);// wait for socket activity or timeout

		// too much to do : sleep
		if(open_connections >= HTTPD_MAX_CONNECTIONS-1)
		sleep(1);

		// Socket Error?
		if(fd == -1 && errno != EINTR)
		{
			perror("select");
			return false;
		}

		// Socket Timeout?
		if(fd == 0)
		{
			// Testoutput for long living threads
			if(++test_counter >= MAX_TIMEOUTS_TO_TEST)
			{
				for(int j=0;j < HTTPD_MAX_CONNECTIONS;j++)
				if(SocketList[j] != NULL) // here is a socket
				log_level_printf(2,"FD-TEST sock:%d handle:%d open:%d\n",SocketList[j]->get_socket(),
						SocketList[j]->handling,SocketList[j]->isOpened);
				test_counter=0;
			}
			// some connection closing previous missed?
			if(++timeout_counter >= MAX_TIMEOUTS_TO_CLOSE)
			{
				CloseConnectionSocketsByTimeout();
				timeout_counter=0;
			}
			continue; // main loop again
		}
		//----------------------------------------------------------------------------------------
		// Check all observed descriptors & check new or re-use Connections
		//----------------------------------------------------------------------------------------
		for(int i = listener; i <= fdmax; i++)
		{
			int slot = -1;
			if(FD_ISSET(i, &read_fds)) // Socket observed?
			{ // we got one!!
				if (i == listener) // handle new connections
				slot = AcceptNewConnectionSocket();
				else // Connection on an existing open Socket = reuse (keep-alive)
				{
					slot = SL_GetExistingSocket(i);
					if(slot>=0)
					log_level_printf(2,"FD: reuse con fd:%d\n",SocketList[slot]->get_socket());
				}
				// prepare Connection handling
				if(slot>=0)
				if(SocketList[slot] != NULL && !SocketList[slot]->handling && SocketList[slot]->isValid)
				{
					log_level_printf(2,"FD: START CON HANDLING con fd:%d\n",SocketList[slot]->get_socket());
					FD_CLR(SocketList[slot]->get_socket(), &master); // remove from master set
					SocketList[slot]->handling = true; // prepares for thread-handling
					if(!handle_connection(SocketList[slot]))// handle this activity
					{ // Can not handle more threads
						char httpstr[]=HTTP_PROTOCOL " 503 Service Unavailable\r\n\r\n";
						SocketList[slot]->Send(httpstr, strlen(httpstr));
						SL_CloseSocketBySlot(slot);
					}
				}
			}
		}// for
		CloseConnectionSocketsByTimeout(); // Check connections to close

	}//while
#else
	while (!terminate) {
		CySocket *newConnectionSock;
		if (!(newConnectionSock = listenSocket.accept())) //Now: Blocking wait
		{
			pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
			pthread_testcancel();
			dperror("Socket accept error. Continue.\n");
			continue;
		}
		log_level_printf(3, "Socket connect from %s\n",
				(listenSocket.get_client_ip()).c_str());
#ifdef Y_CONFIG_USE_OPEN_SSL
		if(Cyhttpd::ConfigList["SSL"]=="true")
		newConnectionSock->initAsSSL(); // make it a SSL-socket
#endif
		handle_connection(newConnectionSock);
	}
#endif
	return true;
}