static void shut_down(void)
{
  int cnum;

  for (cnum = 0; cnum < AVAILABLE_FDS; ++cnum)
    {
      if (connects[cnum].conn_state != CNST_FREE)
        {
          httpd_close_conn(connects[cnum].hc);
        }

      if (connects[cnum].hc != NULL)
        {
          httpd_destroy_conn(connects[cnum].hc);
          httpd_free((void *)connects[cnum].hc);
          connects[cnum].hc = NULL;
        }
    }

  if (hs)
    {
      httpd_server *ths = hs;
      hs = NULL;
      if (ths->listen_fd != -1)
        {
          fdwatch_del_fd(fw, ths->listen_fd);
        }
      httpd_terminate(ths);
    }

  tmr_destroy();
  httpd_free((void *)connects);
}
Esempio n. 2
0
static void *
httpd_session_main(void *data)
#endif
{
  struct hrequest_t *req;
  conndata_t *conn;
  httpd_conn_t *rconn;
  hservice_t *service;
  herror_t status;
  struct timeval start, end, duration;
  int done;

  if (gettimeofday(&start, NULL) == -1)
    log_error("gettimeofday failed (%s)", strerror(errno));

  conn = (conndata_t *) data;

  log_verbose("starting new httpd session on socket %d", conn->sock);

  rconn = httpd_new(&(conn->sock));

  done = 0;
  while (!done)
  {
    log_verbose("starting HTTP request on socket %d (%p)", conn->sock, conn->sock.sock);

    if ((status = hrequest_new_from_socket(&(conn->sock), &req)) != H_OK)
    {
      int code;

      switch ((code = herror_code(status)))
      {
        case HSSL_ERROR_SSLCLOSE:
        case HSOCKET_ERROR_RECEIVE:
          log_error("hrequest_new_from_socket failed (%s)", herror_message(status));
          break;
        default:
          httpd_send_bad_request(rconn, herror_message(status));
          break;
      }
      herror_release(status);
      done = 1;
    }
    else
    {
      char *conn_str;

      _httpd_request_print(req);

      conn_str = hpairnode_get_ignore_case(req->header, HEADER_CONNECTION);
      if (conn_str && strncasecmp(conn_str, "close", 6) == 0)
        done = 1;

      if (!done)
        done = req->version == HTTP_1_0 ? 1 : 0;

      if ((service = httpd_find_service(req->path)))
      {
        log_verbose("service '%s' for '%s' found", service->context, req->path);

	if (service->status == NHTTPD_SERVICE_UP)
	{
          pthread_rwlock_wrlock(&(service->statistics->lock));
          service->statistics->requests++;
          pthread_rwlock_unlock(&(service->statistics->lock));

          if (_httpd_authenticate_request(req, service->auth))
          {
            if (service->func != NULL)
            {
              service->func(rconn, req);

              if (gettimeofday(&end, NULL) == -1)
                log_error("gettimeofday failed (%s)", strerror(errno));
              timersub(&end, &start, &duration);

              pthread_rwlock_wrlock(&(service->statistics->lock));
              service->statistics->bytes_received += rconn->sock->bytes_received;
              service->statistics->bytes_transmitted += rconn->sock->bytes_transmitted;
              timeradd(&(service->statistics->time), &duration, &(service->statistics->time));
              pthread_rwlock_unlock(&(service->statistics->lock));

              if (rconn->out && rconn->out->type == HTTP_TRANSFER_CONNECTION_CLOSE)
              {
                log_verbose("Connection close requested");
                done = 1;
              }
            }
            else
            {
              char buffer[256];

              snprintf(buffer, 256, "service '%s' is not registered properly (service function is NULL)", req->path);
              log_verbose("%s", buffer);
              httpd_send_not_implemented(rconn, buffer);
            }
	  }
          else
          {
            httpd_send_unauthorized(rconn, req->path);
            done = 1;
          }
        }
        else
        {
          char buffer[256];

          sprintf(buffer, "service for '%s' is disabled", req->path);
          log_verbose("%s", buffer);
          httpd_send_internal_error(rconn, buffer);
        }
      }
      else
      {
        char buffer[256];
        sprintf(buffer, "no service for '%s' found", req->path);
        log_verbose("%s", buffer);
	httpd_send_not_implemented(rconn, buffer);
        done = 1;
      }
      hrequest_free(req);
    }
  }

  httpd_free(rconn);

  hsocket_close(&(conn->sock));

#ifdef WIN32
  CloseHandle((HANDLE) conn->tid);
#else
  pthread_attr_destroy(&(conn->attr));
#endif

  conn->flag = CONNECTION_FREE;

#ifdef WIN32
  _endthread();
  return 0;
#else
  /* pthread_exits automagically */
  return NULL;
#endif
}
Esempio n. 3
0
int http_get(struct httpd * httpd, struct httpctl * ctl)
{
	int (* cgi)(struct tcp_pcb * tp);
	char buf[128];
//	int content_type;
//	int content_len;
//	char * opt;	
	char * ext;	
	struct stat sb;
	int type;
	int hash;
	int size;
	int ret;
	int fd;
	int n;

	strcpy(buf, httpd->root);
	strcat(buf, ctl->uri);

//	for (opt = buf; (*opt); opt++) {
 //		if (*opt == '?') {
//			*opt++ = '\0';
//			break;
//		}
//	}
	
	DBG(DBG_INFO, "path=%s", buf);

	if ((ret = stat(buf, &sb)) < 0) {
		DBG(DBG_ERROR, "404 File Not Found");
		httpd_404(ctl->tp);
		return ret;
	}

	if (S_ISDIR(sb.st_mode)) {
		DBG(DBG_INFO, "is a directory");
		strcat(buf, "/");
		strcat(buf, httpd_page_default);
		if ((ret = stat(buf, &sb)) < 0) {
			strcpy(buf, httpd->root);
			strcat(buf, ctl->uri);	
			return httpd_dirlist(httpd, ctl);
		}
	}

	if (!S_ISREG(sb.st_mode)) {
		DBG(DBG_ERROR, "403 Forbidden");
		httpd_403(ctl->tp);
		return -1;
	}

	if ((fd = open(buf, O_RDONLY)) < 0) {
		DBG(DBG_ERROR, "404 File Not Found");
		httpd_404(ctl->tp);
		return -1;
	}

	ret = 0;

	if ((ext = strrchr(buf, '.')) != NULL) {
		DBG(DBG_INFO, "extension=%s", ext);
		/* skip the '.' */
		ext++;
		hash = mk_ext_hash(ext);

		switch (hash) {
		case EXT_CGI:
			DBG(DBG_INFO, "cgi");
			goto dynamic_cgi;
		case EXT_TXT:
			DBG(DBG_INFO, "text");
			type = text_plain; 
			break;
		case EXT_JPEG:
		case EXT_JPG:
			DBG(DBG_INFO, "jpeg");
			type = image_jpeg; 
			break;
		case EXT_ICO:
			DBG(DBG_INFO, "ico");
		case EXT_GIF:
			DBG(DBG_INFO, "gif");
			type = image_gif; 
			break;
		case EXT_PNG:
			DBG(DBG_INFO, "png");
			type = image_png; 
			break;
		case EXT_JS:
			DBG(DBG_INFO, "js");
			type = application_x_javascript;
			break;
		case EXT_HTML:
		case EXT_HTM:
			DBG(DBG_INFO, "html");
		default:
			type = text_html; 
			break;
		}

		httpd_200(ctl->tp, type);

		while ((n = read(fd, buf, 128)) > 0) {
			if (tcp_send(ctl->tp, buf, n, 0) <= 0) {
				DBG(DBG_ERROR, "tcp_send()");
				ret = -1;
				break;
			}
		}

	} else {
dynamic_cgi:

		size = lseek(fd, 0, SEEK_END);
		DBG(DBG_TRACE, "size=%d", size);

		cgi = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);

		DBG(DBG_TRACE, "cgi=%p", cgi);

		ret = cgi(ctl->tp);
	}

	close(fd);

#if 0
	DBG(DBG_INFO, "file uid=%d", info.fi_uid);

	if (info.fi_uid < __httpd->uid) {
		unsigned int uid;
		
		DBG(DBG_INFO, "info.fi_uid=%d < httpd->uid=%d, auth required", 
			info.fi_uid, __httpd->uid);
		uid = httpd_auth(__http->httpd, __http->usr, __http->pwd);
		if (info.fi_uid < uid) {
			DBG(DBG_ERROR, "401 Unauthorized, uid=%d", uid);
			httpd_401_auth(__tp);
			return -1;
		}
	}

	content_type = __http->ctype;
	content_len = __http->ctlen;

	if (info.fi_mime != _code_) {
		/* detach the PCB */
		tcp_attach(__tp, NULL, __httpd);
		/* release the control structure */
		httpd_free(__httpd, __http);

		httpd_send(__tp, info.fi_mime, (char *)info.fi_data, info.fi_size);
		tcp_close(__tp);
		return 0;
	}

	/* dynamic cgi */
	DBG(DBG_INFO, "dynamic page");
	cgi_call = (httpd_cgi_t)info.fi_data;

	/* reuse the allocated buffer */
	cgi = (struct cgistate *)__http;
	/* XXX: */
	cgi->httpd = __httpd;
	cgi->callback = NULL;

	/* attach the PCB to the CGI handler */
	tcp_attach(__tp, (tcp_callback_t)httpd_cgi_handler, cgi);

	if (cgi_call(__tp, opt, content_type, content_len) < 0) {
		/* close the tcp pcb */
		tcp_close(__tp);
	} else {
		/* if the CGI is still detached, close-it */
		if (cgi->callback == NULL)
			tcp_close(__tp);		
	}
#endif



	return ret;
}
Esempio n. 4
0
File: main.c Progetto: lundman/llink
int main( int argc, char **argv )
{

	// Read any command line arguments from our friend the user.
	arguments(argc, argv);

	// Catch some signals so can exit cleanly

	signal(SIGINT, exit_interrupt);
#ifndef WIN32
	signal(SIGHUP,  exit_interrupt);
	signal(SIGTERM, exit_interrupt);
	signal(SIGPIPE, SIG_IGN);
    if (debug_on)
        setvbuf(stdout, NULL, _IONBF, 0);
#endif

	printf("%s - Jorgen Lundman v%s %s %s\n\n",
		argv ? argv[0] : "llink",
		   VERSION,
		   VERSION_STRING,
#if WITH_DVDREAD
		   "(libdvdread)"
#else

#if HAVE_CLINKC
		   "(libdvdnav, ClinkC)"
#else
		   "(libdvdnav)"
#endif
#endif
		   );


	lion_buffersize(conf_buffersize);
	//lion_buffersize(2352);

	if (lion_init()) {
		printf("Failed to initialize lion/networking\n");
		exit(-1);
	}

	debugf("\n");

	// Read configuration file, if any
	// Warning, calls lion_poll until done.
	conf_init();

	debugf("[main] initialising...\n");

	// Warning, calls lion_poll until done.
	mime_init();

	// Warning, calls lion_poll until done.
	skin_init();

	ssdp_init();

	httpd_init();

	request_init();

	root_init();

	llrar_init();

	visited_init();

	cgicmd_init();

#ifdef EXTERNAL
	external_init();
#endif

	printf("[main] ready!\n");

	// Background?
#ifndef WIN32
	if (!foreground) {
		if (fork()) exit(0);
		setsid();

        if (conf_pidfile) {
            FILE *fd;
            if ((fd = fopen(conf_pidfile, "w"))) {
                fprintf(fd, "%u\r\n", getpid());
                fclose(fd);
            }
        }
	}
#endif

    cupnp_init();


	// Scan for media
	if (conf_xmlscan) {
		signal(SIGINT, SIG_DFL);
		xmlscan_run();
		do_exit = 1;
	}


	query_init();

#ifdef WIN32
	SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
#endif

	// The main loop
	while ( !do_exit ) {

        // Was 250,0 - we should probably let users control this in
        // conf settings.
		if (lion_poll(0, 1)<0) do_exit=1;

		request_events();

#ifdef EXTERNAL
		external_resume();
#endif

	}

	printf("\n[main] releasing resources...\n");

	query_free();

    cupnp_free();

#ifdef EXTERNAL
	external_free();
#endif

	root_free();

	cgicmd_free();

	visited_free();

	llrar_free();

	request_free();

	httpd_free();

	ssdp_free();

	skin_free();

	mime_free();

	conf_free();

#ifndef WIN32  // Crashed when releasing spawned processes, until i can fix:
	lion_free();
#endif

	debugf("[main] done.\n");

	return 0;

}