Example #1
0
gboolean
eo_save_entry(const gchar *save_as_filename, export_object_entry_t *entry, gboolean show_err)
{
    int to_fd;
    gint64 bytes_left;
    int bytes_to_write;
    ssize_t bytes_written;
    guint8 *ptr;
    int err;

    to_fd = ws_open(save_as_filename, O_WRONLY | O_CREAT | O_EXCL |
             O_BINARY, 0644);
    if(to_fd == -1) { /* An error occurred */
        if (show_err)
            open_failure_alert_box(save_as_filename, errno, TRUE);
        return FALSE;
    }

    /*
     * The third argument to _write() on Windows is an unsigned int,
     * so, on Windows, that's the size of the third argument to
     * ws_write().
     *
     * The third argument to write() on UN*X is a size_t, although
     * the return value is an ssize_t, so one probably shouldn't
     * write more than the max value of an ssize_t.
     *
     * In either case, there's no guarantee that a gint64 such as
     * payload_len can be passed to ws_write(), so we write in
     * chunks of, at most 2^31 bytes.
     */
    ptr = entry->payload_data;
    bytes_left = entry->payload_len;
    while (bytes_left != 0) {
        if (bytes_left > 0x40000000)
            bytes_to_write = 0x40000000;
        else
            bytes_to_write = (int)bytes_left;
        bytes_written = ws_write(to_fd, ptr, bytes_to_write);
        if(bytes_written <= 0) {
            if (bytes_written < 0)
                err = errno;
            else
                err = WTAP_ERR_SHORT_WRITE;
            if (show_err)
                write_failure_alert_box(save_as_filename, err);
            ws_close(to_fd);
            return FALSE;
        }
        bytes_left -= bytes_written;
        ptr += bytes_written;
    }
    if (ws_close(to_fd) < 0) {
        if (show_err)
            write_failure_alert_box(save_as_filename, errno);
        return FALSE;
    }

    return TRUE;
}
Example #2
0
/* save the SSL Session Keys */
static gboolean
savesslkeys_save_clicked_cb(char *file, gchar *keylist)
{
    int fd;

    fd = ws_open(file, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
    if (fd == -1) {
        open_failure_alert_box(file, errno, TRUE);
        return FALSE;
    }
    /*
     * Thanks, Microsoft, for not using size_t for the third argument to
     * _write().  Presumably this string will be <= 4GiB long....
     */
    if (ws_write(fd, keylist, (unsigned int)strlen(keylist)) < 0) {
        write_failure_alert_box(file, errno);
        ws_close(fd);
        return FALSE;
    }
    if (ws_close(fd) < 0) {
        write_failure_alert_box(file, errno);
        return FALSE;
    }

    g_free(keylist);
    return TRUE;
}
Example #3
0
/*
 * Frees all memory allocated by the ringbuffer
 */
void
ringbuf_error_cleanup(void)
{
  unsigned int i;

  /* try to close via wtap */
  if (rb_data.pdh != NULL) {
    if (libpcap_dump_close(rb_data.pdh, NULL)) {
      rb_data.fd = -1;
    }
    rb_data.pdh = NULL;
  }

  /* close directly if still open */
  /* XXX - it shouldn't still be open; "libpcap_dump_close()" should leave the
     file closed even if it fails */
  if (rb_data.fd != -1) {
    ws_close(rb_data.fd);
    rb_data.fd = -1;
  }

  if (rb_data.files != NULL) {
    for (i=0; i < rb_data.num_files; i++) {
      if (rb_data.files[i].name != NULL) {
        ws_unlink(rb_data.files[i].name);
      }
    }
  }
  /* free the memory */
  ringbuf_free();
}
Example #4
0
/* update the time and size of this file in the list */
void
fileset_update_file(const char *path)
{
    int fh, result;
    ws_statb64 buf;
    fileset_entry *entry = NULL;
    GList *entry_list;

    fh = ws_open( path, O_RDONLY, 0000 /* no creation so don't matter */);
    if(fh !=  -1) {

        /* Get statistics */
        result = ws_fstat64( fh, &buf );

        /* Show statistics if they are valid */
        if( result == 0 ) {
            entry_list = g_list_find_custom(set.entries, path,
                                            fileset_find_by_path);

            if (entry_list) {
                entry = (fileset_entry *) entry_list->data;
                entry->ctime    = buf.st_ctime;
                entry->mtime    = buf.st_mtime;
                entry->size     = buf.st_size;
            }
        }

        ws_close(fh);
    }
}
Example #5
0
/*
 * Frees all memory allocated by the ringbuffer
 */
void
ringbuf_error_cleanup(void)
{
  unsigned int i;

  /* try to close via wtap */
  if (rb_data.pdh != NULL) {
    if (fclose(rb_data.pdh) == 0) {
      rb_data.fd = -1;
    }
    rb_data.pdh = NULL;
  }

  /* close directly if still open */
  if (rb_data.fd != -1) {
    ws_close(rb_data.fd);
    rb_data.fd = -1;
  }

  if (rb_data.files != NULL) {
    for (i=0; i < rb_data.num_files; i++) {
      if (rb_data.files[i].name != NULL) {
        ws_unlink(rb_data.files[i].name);
      }
    }
  }
  /* free the memory */
  ringbuf_free();
}
Example #6
0
void ws_destroy(wsh_t *wsh)
{

	if (!wsh) {
		return;
	}

	if (!wsh->down) {
		ws_close(wsh, WS_NONE);
	}

	if (wsh->down > 1) {
		return;
	}
	
	wsh->down = 2;

	if (wsh->write_buffer) {
		free(wsh->write_buffer);
		wsh->write_buffer = NULL;
		wsh->write_buffer_len = 0;
	}

	if (wsh->ssl) {
		int code;
		do {
			code = SSL_shutdown(wsh->ssl);
		} while (code == -1 && SSL_get_error(wsh->ssl, code) == SSL_ERROR_WANT_READ);

		SSL_free(wsh->ssl);
		wsh->ssl = NULL;
	}
}
Example #7
0
void u3_register_pid()
{
  int	pid;
  int   pid_fd;
  char *u3hostexecpath;
  int   pf_size;

  if((u3hostexecpath =
#ifdef _WIN32
      getenv_utf8
#else
      getenv
#endif
      ("U3_HOST_EXEC_PATH")) != NULL) {

    pid = getpid();

    pf_size = (int) strlen(u3hostexecpath) + 32;
    pid_file = g_malloc(pf_size);

    g_snprintf(pid_file, pf_size, "%s\\%d.pid", u3hostexecpath, pid);

    pid_fd = ws_open(pid_file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);

    if(pid_fd != -1)
      ws_close(pid_fd);
    else {
      g_free(pid_file);
      pid_file = NULL;
    }
  }
}
Example #8
0
static void ws_conn_clean(struct tcp_connection* c)
{
	struct ws_data *d = (struct ws_data*)c->proto_data;

	if (d) {

		if (c->state == S_CONN_OK && !is_tcp_main) {
			switch (d->code) {
			case WS_ERR_NOSEND:
				break;
			case WS_ERR_NONE:
				WS_CODE(c) = WS_ERR_NORMAL;
			default:
				ws_close(c);
				break;
			}
		}

		shm_free(d);
		c->proto_data = NULL;

	}

	tls_conn_clean(c);
}
Example #9
0
static void
followFileOpen(
  follow_t *fp
  )
{
  int   fd;
  char *tempfilep;

  if (fp->type == type_TCP && data_out_file != NULL)
  {
    followExit("Only one TCP stream can be followed at a time.");
  }

  followFileClose(fp);

  fd = create_tempfile(&tempfilep, "follow");
  if (fd == -1)
  {
    followExit("Error creating temp file.");
  }

  fp->filenamep = g_strdup(tempfilep);
  if (fp->filenamep == NULL)
  {
    ws_close(fd);
    ws_unlink(tempfilep);
    followExit("Error duping temp file name.");
  }

  fp->filep = fdopen(fd, "w+b");
  if (fp->filep == NULL)
  {
    ws_close(fd);
    ws_unlink(fp->filenamep);
    g_free(fp->filenamep);
    fp->filenamep = NULL;
    followExit("Error opening temp file stream.");
  }

  if (fp->type == type_TCP)
  {
    data_out_file = fp->filep;
  }
}
Example #10
0
/* Seed the random-number generator */
void
randpkt_seed(void)
{
	unsigned int	randomness;
	time_t		now;
#ifndef _WIN32
	int 		fd;
	ssize_t		ret;

#define RANDOM_DEV "/dev/urandom"

	/*
	 * Assume it's at least worth trying /dev/urandom on UN*X.
	 * If it doesn't exist, fall back on time().
	 *
	 * XXX - Use CryptGenRandom on Windows?
	 */
	fd = ws_open(RANDOM_DEV, O_RDONLY);
	if (fd == -1) {
		if (errno != ENOENT) {
			fprintf(stderr,
				"randpkt: Could not open " RANDOM_DEV " for reading: %s\n",
				g_strerror(errno));
			exit(2);
		}
		goto fallback;
	}

	ret = ws_read(fd, &randomness, sizeof randomness);
	if (ret == -1) {
		fprintf(stderr,
			"randpkt: Could not read from " RANDOM_DEV ": %s\n",
			g_strerror(errno));
		exit(2);
	}
	if ((size_t)ret != sizeof randomness) {
		fprintf(stderr,
			"randpkt: Tried to read %lu bytes from " RANDOM_DEV ", got %ld\n",
			(unsigned long)sizeof randomness, (long)ret);
		exit(2);
	}
	srand(randomness);
	ws_close(fd);
	return;

fallback:
#endif
	now = time(NULL);
	randomness = (unsigned int) now;

	srand(randomness);
}
Example #11
0
static int ssh_open_remote_connection(const char* hostname, const unsigned int port, const char* username, const char* password,
	const char* sshkey, const char* sshkey_passphrase, const char* iface, const char* cfilter, const char* capture_bin,
	const unsigned long int count, const char* fifo)
{
	ssh_session sshs = NULL;
	ssh_channel channel = NULL;
	int fd = STDOUT_FILENO;
	int ret = EXIT_FAILURE;
	char* err_info = NULL;

	if (g_strcmp0(fifo, "-")) {
		/* Open or create the output file */
		fd = ws_open(fifo, O_WRONLY, 0640);
		if (fd == -1) {
			fd = ws_open(fifo, O_WRONLY | O_CREAT, 0640);
			if (fd == -1) {
				errmsg_print("Error creating output file: %s", g_strerror(errno));
				return EXIT_FAILURE;
			}
		}
	}

	sshs = create_ssh_connection(hostname, port, username, password, sshkey, sshkey_passphrase, &err_info);

	if (!sshs) {
		errmsg_print("Error creating connection: %s", err_info);
		goto cleanup;
	}

	channel = run_ssh_command(sshs, capture_bin, iface, cfilter, count);
	if (!channel)
		goto cleanup;

	/* read from channel and write into fd */
	ssh_loop_read(channel, fd);

	ret = EXIT_SUCCESS;
cleanup:
	if (err_info)
		errmsg_print("%s", err_info);
	g_free(err_info);

	/* clean up and exit */
	ssh_cleanup(&sshs, &channel);

	if (g_strcmp0(fifo, "-"))
		ws_close(fd);
	return ret;
}
Example #12
0
/* download a complete file from the internet */
int
download_file(const char *url, const char *filename) {
    netio_ie5_t * conn;
    char buf[100];
    int chunk_len;
    int fd;
    int stream_len;
    int ret = 0;


    /* open output file */
    fd = ws_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
    if(fd == -1) {
        g_warning("Couldn't open output file %s!", filename);
        return -1;
    }

    /* connect to url */
    conn = netio_ie5_connect (url);
    if (conn == NULL) {
        g_warning("Couldn't connect to %s!", url);
        return -1;
    }

    do {
		/* XXX - maybe add a progress bar here */

        /* read some bytes from the url */
        chunk_len = netio_ie5_read (conn, buf, sizeof(buf));

        /* write bytes to the output file */
        stream_len = ws_write( fd, buf, chunk_len);
        if(stream_len != chunk_len) {
            g_warning("output failed: stream_len %u != chunk_len %u", stream_len, chunk_len);
            ret = -1;
            break;
        }
    } while(chunk_len > 0);

    netio_ie5_disconnect(conn);

    ws_close(fd);

    return ret;
}
Example #13
0
void onmsg(ws_t ws, char *msg, uint64_t len, int binary, void *arg)
{
	int *echo_count = (int *)arg;
	
	printf("Message %d: \"%s\"\n", *echo_count, msg);
	(*echo_count)--;

	{
		char *send_msg = strdup(((*echo_count % 2) == 0) ? "Hello" : "World");
		ws_send_msg(ws, send_msg);
		free(send_msg);
	}

	if (*echo_count == 0)
	{
		printf("Got last echo\n");
		ws_close(ws);
	}
}
Example #14
0
/*
 * Switches to the next ringbuffer file
 */
gboolean
ringbuf_switch_file(FILE **pdh, gchar **save_file, int *save_file_fd, int *err)
{
  int     next_file_index;
  rb_file *next_rfile = NULL;

  /* close current file */

  if (fclose(rb_data.pdh) == EOF) {
    if (err != NULL) {
      *err = errno;
    }
    ws_close(rb_data.fd);	/* XXX - the above should have closed this already */
    rb_data.pdh = NULL;	/* it's still closed, we just got an error while closing */
    rb_data.fd = -1;
    return FALSE;
  }

  rb_data.pdh = NULL;
  rb_data.fd  = -1;

  /* get the next file number and open it */

  rb_data.curr_file_num++ /* = next_file_num*/;
  next_file_index = (rb_data.curr_file_num) % rb_data.num_files;
  next_rfile = &rb_data.files[next_file_index];

  if (ringbuf_open_file(next_rfile, err) == -1) {
    return FALSE;
  }

  if (ringbuf_init_libpcap_fdopen(err) == NULL) {
    return FALSE;
  }

  /* switch to the new file */
  *save_file = next_rfile->name;
  *save_file_fd = rb_data.fd;
  (*pdh) = rb_data.pdh;

  return TRUE;
}
Example #15
0
/*
 * Calls libpcap_dump_close() for the current ringbuffer file
 */
gboolean
ringbuf_libpcap_dump_close(gchar **save_file, int *err)
{
  gboolean  ret_val = TRUE;

  /* close current file, if it's open */
  if (rb_data.pdh != NULL) {
    if (!libpcap_dump_close(rb_data.pdh, err)) {
      ws_close(rb_data.fd);
      ret_val = FALSE;
    }

    rb_data.pdh = NULL;
    rb_data.fd  = -1;
  }

  /* set the save file name to the current file */
  *save_file = rb_data.files[rb_data.curr_file_num % rb_data.num_files].name;
  return ret_val;
}
Example #16
0
/* we know this file is part of the set, so add it */
static fileset_entry *
fileset_add_file(const char *dirname, const char *fname, gboolean current)
{
    int fh, result;
    struct stat buf;
    char *path;
    fileset_entry *entry = NULL;


    path = g_strdup_printf("%s%s", dirname, fname);

    fh = ws_open( path, O_RDONLY, 0000 /* no creation so don't matter */);
    if(fh !=  -1) {

        /* Get statistics */
        result = fstat( fh, &buf );

        /* Show statistics if they are valid */
        if( result == 0 ) {
            entry = (fileset_entry *)g_malloc(sizeof(fileset_entry));

            entry->fullname = g_strdup(path);
            entry->name     = g_strdup(fname);
            entry->ctime    = buf.st_ctime;
            entry->mtime    = buf.st_mtime;
            entry->size     = buf.st_size;
            entry->current  = current;

            set.entries = g_list_append(set.entries, entry);
        }

        ws_close(fh);
    }

    g_free(path);

    return entry;
}
Example #17
0
/* Opens a file and prepares a wtap struct.
   If "do_random" is TRUE, it opens the file twice; the second open
   allows the application to do random-access I/O without moving
   the seek offset for sequential I/O, which is used by Wireshark
   so that it can do sequential I/O to a capture file that's being
   written to as new packets arrive independently of random I/O done
   to display protocol trees for packets when they're selected. */
wtap* wtap_open_offline(const char *filename, int *err, char **err_info,
			gboolean do_random)
{
	struct stat statb;
	wtap	*wth;
	unsigned int	i;
	gboolean use_stdin = FALSE;

	/* open standard input if filename is '-' */
	if (strcmp(filename, "-") == 0)
		use_stdin = TRUE;

	/* First, make sure the file is valid */
	if (use_stdin) {
		if (fstat(0, &statb) < 0) {
			*err = errno;
			return NULL;
		}
	} else {
		if (ws_stat(filename, &statb) < 0) {
			*err = errno;
			return NULL;
		}
	}
	if (S_ISFIFO(statb.st_mode)) {
		/*
		 * Opens of FIFOs are allowed only when not opening
		 * for random access.
		 *
		 * XXX - currently, we do seeking when trying to find
		 * out the file type, so we don't actually support
		 * opening FIFOs.  However, we may eventually
		 * do buffering that allows us to do at least some
		 * file type determination even on pipes, so we
		 * allow FIFO opens and let things fail later when
		 * we try to seek.
		 */
		if (do_random) {
			*err = WTAP_ERR_RANDOM_OPEN_PIPE;
			return NULL;
		}
	} else if (S_ISDIR(statb.st_mode)) {
		/*
		 * Return different errors for "this is a directory"
		 * and "this is some random special file type", so
		 * the user can get a potentially more helpful error.
		 */
		*err = EISDIR;
		return NULL;
	} else if (! S_ISREG(statb.st_mode)) {
		*err = WTAP_ERR_NOT_REGULAR_FILE;
		return NULL;
	}

	/*
	 * We need two independent descriptors for random access, so
	 * they have different file positions.  If we're opening the
	 * standard input, we can only dup it to get additional
	 * descriptors, so we can't have two independent descriptors,
	 * and thus can't do random access.
	 */
	if (use_stdin && do_random) {
		*err = WTAP_ERR_RANDOM_OPEN_STDIN;
		return NULL;
	}

	errno = ENOMEM;
	wth = (wtap *)g_malloc(sizeof(wtap));
	if (wth == NULL) {
		*err = errno;
		return NULL;
	}

	/* Open the file */
	errno = WTAP_ERR_CANT_OPEN;
	if (use_stdin) {
		/*
		 * We dup FD 0, so that we don't have to worry about
		 * an fclose or gzclose of wth->fh closing the standard
		 * input of the process.
		 */
		wth->fd = ws_dup(0);
#ifdef _WIN32
		_setmode(wth->fd, O_BINARY);
#endif
	} else
		wth->fd = ws_open(filename, O_RDONLY|O_BINARY, 0000 /* no creation so don't matter */);
	if (wth->fd < 0) {
		*err = errno;
		g_free(wth);
		return NULL;
	}
	if (!(wth->fh = filed_open(wth->fd, "rb"))) {
		*err = errno;
		ws_close(wth->fd);
		g_free(wth);
		return NULL;
	}

	if (do_random) {
		if (!(wth->random_fh = file_open(filename, "rb"))) {
			*err = errno;
			file_close(wth->fh);
			g_free(wth);
			return NULL;
		}
	} else
		wth->random_fh = NULL;

	/* initialization */
	wth->file_encap = WTAP_ENCAP_UNKNOWN;
	wth->data_offset = 0;
	wth->subtype_sequential_close = NULL;
	wth->subtype_close = NULL;
	wth->tsprecision = WTAP_FILE_TSPREC_USEC;
	wth->priv = NULL;

	init_open_routines();

	/* Try all file types */
	for (i = 0; i < open_routines_arr->len; i++) {
		/* Seek back to the beginning of the file; the open routine
		   for the previous file type may have left the file
		   position somewhere other than the beginning, and the
		   open routine for this file type will probably want
		   to start reading at the beginning.

		   Initialize the data offset while we're at it. */
		if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
			/* I/O error - give up */
			if (wth->random_fh != NULL)
				file_close(wth->random_fh);
			file_close(wth->fh);
			g_free(wth);
			return NULL;
		}
		wth->data_offset = 0;

		switch ((*open_routines[i])(wth, err, err_info)) {

		case -1:
			/* I/O error - give up */
			if (wth->random_fh != NULL)
				file_close(wth->random_fh);
			file_close(wth->fh);
			g_free(wth);
			return NULL;

		case 0:
			/* No I/O error, but not that type of file */
			break;

		case 1:
			/* We found the file type */
			goto success;
		}
	}

	/* Well, it's not one of the types of file we know about. */
	if (wth->random_fh != NULL)
		file_close(wth->random_fh);
	file_close(wth->fh);
	g_free(wth);
	*err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
	return NULL;

success:
	wth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
	buffer_init(wth->frame_buffer, 1500);
	return wth;
}
Example #18
0
int ws_handshake(wsh_t *wsh)
{
	char key[256] = "";
	char version[5] = "";
	char proto[256] = "";
	char proto_buf[384] = "";
	char input[256] = "";
	unsigned char output[SHA1_HASH_SIZE] = "";
	char b64[256] = "";
	char respond[512] = "";
	ssize_t bytes;
	char *p, *e = 0;

	if (wsh->sock == ws_sock_invalid) {
		return -3;
	}

	while((bytes = ws_raw_read(wsh, wsh->buffer + wsh->datalen, wsh->buflen - wsh->datalen, WS_BLOCK)) > 0) {
		wsh->datalen += bytes;
		if (strstr(wsh->buffer, "\r\n\r\n") || strstr(wsh->buffer, "\n\n")) {
			break;
		}
	}

	if (bytes > sizeof(wsh->buffer) -1) {
		goto err;
	}

	*(wsh->buffer + wsh->datalen) = '\0';
	
	if (strncasecmp(wsh->buffer, "GET ", 4)) {
		goto err;
	}
	
	p = wsh->buffer + 4;
	
	e = strchr(p, ' ');
	if (!e) {
		goto err;
	}

	wsh->uri = malloc((e-p) + 1);
	strncpy(wsh->uri, p, e-p);
	*(wsh->uri + (e-p)) = '\0';

	cheezy_get_var(wsh->buffer, "Sec-WebSocket-Key", key, sizeof(key));
	cheezy_get_var(wsh->buffer, "Sec-WebSocket-Version", version, sizeof(version));
	cheezy_get_var(wsh->buffer, "Sec-WebSocket-Protocol", proto, sizeof(proto));
	
	if (!*key) {
		goto err;
	}
		
	snprintf(input, sizeof(input), "%s%s", key, WEBSOCKET_GUID);
	sha1_digest(output, input);
	b64encode((unsigned char *)output, SHA1_HASH_SIZE, (unsigned char *)b64, sizeof(b64));

	if (*proto) {
		snprintf(proto_buf, sizeof(proto_buf), "Sec-WebSocket-Protocol: %s\r\n", proto);
	}

	snprintf(respond, sizeof(respond), 
			 "HTTP/1.1 101 Switching Protocols\r\n"
			 "Upgrade: websocket\r\n"
			 "Connection: Upgrade\r\n"
			 "Sec-WebSocket-Accept: %s\r\n"
			 "%s\r\n",
			 b64,
			 proto_buf);
	respond[511] = 0;

	if (ws_raw_write(wsh, respond, strlen(respond)) != (ssize_t)strlen(respond)) {
		goto err;
	}

	wsh->handshake = 1;

	return 0;

 err:

	if (!wsh->stay_open) {

		snprintf(respond, sizeof(respond), "HTTP/1.1 400 Bad Request\r\n"
				 "Sec-WebSocket-Version: 13\r\n\r\n");
		respond[511] = 0;

		ws_raw_write(wsh, respond, strlen(respond));

		ws_close(wsh, WS_NONE);
	}

	return -1;

}
Example #19
0
abyss_bool websocket_hook(TSession *r)
{
	wsh_t *wsh;
	int ret;
	int i;
	ws_opcode_t opcode;
	uint8_t *data;
	switch_event_node_t *nodes[MAX_EVENT_BIND_SLOTS];
	int node_count = 0;
	char *p;
	char *key = NULL;
	char *version = NULL;
	char *proto = NULL;
	char *upgrade = NULL;

	for (i = 0; i < r->requestHeaderFields.size; i++) {
		TTableItem * const item = &r->requestHeaderFields.item[i];

		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "headers %s: %s\n", item->name, item->value);
	}

	key = RequestHeaderValue(r, "sec-websocket-key");
	version = RequestHeaderValue(r, "sec-websocket-version");
	proto = RequestHeaderValue(r, "sec-websocket-protocol");
	upgrade = RequestHeaderValue(r, "upgrade");

	if (!key || !version || !proto || !upgrade) return FALSE;
	if (strncasecmp(upgrade, "websocket", 9) || strncasecmp(proto, "websocket", 9)) return FALSE;

	wsh = ws_init(r);
	if (!wsh) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "websocket error %d\n", ret);
		return FALSE;
	}

	ret = ws_handshake_kvp(wsh, key, version, proto);
	if (ret < 0) wsh->down = 1;

	if (ret != 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "handshake error %d\n", ret);
		return FALSE;
	}

	if (switch_event_bind_removable("websocket", SWITCH_EVENT_CUSTOM, "websocket::stophook", stop_hook_event_handler, wsh, &nodes[node_count++]) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't bind!\n");
		node_count--;
	}

	while (!wsh->down) {
		int bytes = ws_read_frame(wsh, &opcode, &data);

		if (bytes < 0) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d %s\n", opcode, (char *)data);
			switch_yield(100000);
			continue;
		}

		switch (opcode) {
			case WSOC_CLOSE:
				ws_close(wsh, 1000);
				break;
			case WSOC_CONTINUATION:
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "continue\n");
				continue;
			case WSOC_TEXT:
				p = data;
				if (!p) continue;
				if (!strncasecmp(data, "event ", 6)) {
					switch_event_types_t type;
					char *subclass;

					if (node_count == MAX_EVENT_BIND_SLOTS - 1) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot subscribe more than %d events\n", node_count);
						continue;
					}
					p += 6;
					if (p = strchr(p, ' ')) p++;
					if (!strncasecmp(p, "json ", 5)) {
						p += 5;
					} else if (!strncasecmp(p, "xml ", 4)) {
						p += 4;
					} else if (!strncasecmp(p, "plain ", 6)) {
						p += 6;
					}
					if (!*p) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "missing event type in [%s]\n", data);
						break;
					} else {
					}
					if (subclass = strchr(p, ' ')) {
						*subclass++ = '\0';
						if (!*subclass) {
							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing subclass\n");
							continue;
						}
					} else {
						subclass = SWITCH_EVENT_SUBCLASS_ANY;
					}

					if (switch_name_event(p, &type) != SWITCH_STATUS_SUCCESS) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown event %s\n", p);
						continue;
					}

					if (switch_event_bind_removable("websocket", type, subclass, event_handler, wsh, &nodes[node_count++]) != SWITCH_STATUS_SUCCESS) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't bind!\n");
						node_count--;
						continue;
					} else {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Bind %s\n", data);
					}

				}
				break;
			default:
				break;
		}
	}

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "wsh->down = %d, node_count = %d\n", wsh->down, node_count);

	switch_yield(2000);
	while (--node_count >= 0) switch_event_unbind(&nodes[node_count]);

	switch_safe_free(wsh);

	return FALSE;
}
Example #20
0
ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
{
	
	ssize_t need = 2;
	char *maskp;
	int ll = 0;
	int frag = 0;

 again:
	need = 2;
	maskp = NULL;
	*data = NULL;

	ll = establish_logical_layer(wsh);

	if (ll < 0) {
		return ll;
	}

	if (wsh->down) {
		return -1;
	}

	if (!wsh->handshake) {
		return ws_close(wsh, WS_PROTO_ERR);
	}

	if ((wsh->datalen = ws_raw_read(wsh, wsh->buffer, 9, wsh->block)) < 0) {
		if (wsh->datalen == -2) {
			return -2;
		}
		return ws_close(wsh, WS_PROTO_ERR);
	}
	
	if (wsh->datalen < need) {
		if ((wsh->datalen += ws_raw_read(wsh, wsh->buffer + wsh->datalen, 9 - wsh->datalen, WS_BLOCK)) < need) {
			/* too small - protocol err */
			return ws_close(wsh, WS_PROTO_ERR);
		}
	}

	*oc = *wsh->buffer & 0xf;

	switch(*oc) {
	case WSOC_CLOSE:
		{
			wsh->plen = wsh->buffer[1] & 0x7f;
			*data = (uint8_t *) &wsh->buffer[2];
			return ws_close(wsh, 1000);
		}
		break;
	case WSOC_CONTINUATION:
	case WSOC_TEXT:
	case WSOC_BINARY:
	case WSOC_PING:
	case WSOC_PONG:
		{
			int fin = (wsh->buffer[0] >> 7) & 1;
			int mask = (wsh->buffer[1] >> 7) & 1;
			
			if (fin) {
				if (*oc == WSOC_CONTINUATION) {
					frag = 1;
				} else {
					frag = 0;
				}
			}

			if (mask) {
				need += 4;
				
				if (need > wsh->datalen) {
					/* too small - protocol err */
					*oc = WSOC_CLOSE;
					return ws_close(wsh, WS_PROTO_ERR);
				}
			}

			wsh->plen = wsh->buffer[1] & 0x7f;
			wsh->payload = &wsh->buffer[2];

			if (wsh->plen == 127) {
				uint64_t *u64;

				need += 8;

				if (need > wsh->datalen) {
					/* too small - protocol err */
					*oc = WSOC_CLOSE;
					return ws_close(wsh, WS_PROTO_ERR);
				}

				u64 = (uint64_t *) wsh->payload;
				wsh->payload += 8;

				wsh->plen = ntohl((u_long)*u64);

			} else if (wsh->plen == 126) {
				uint16_t *u16;

				need += 2;

				if (need > wsh->datalen) {
					/* too small - protocol err */
					*oc = WSOC_CLOSE;
					return ws_close(wsh, WS_PROTO_ERR);
				}

				u16 = (uint16_t *) wsh->payload;
				wsh->payload += 2;
				wsh->plen = ntohs(*u16);
			}

			if (mask) {
				maskp = (char *)wsh->payload;
				wsh->payload += 4;
			}

			need = (wsh->plen - (wsh->datalen - need));

			if (need < 0) {
				/* invalid read - protocol err .. */
				*oc = WSOC_CLOSE;
				return ws_close(wsh, WS_PROTO_ERR);
			}

			if ((need + wsh->datalen) > (ssize_t)wsh->buflen) {
				/* too big - Ain't nobody got time fo' dat */
				*oc = WSOC_CLOSE;
				return ws_close(wsh, WS_DATA_TOO_BIG);				
			}

			wsh->rplen = wsh->plen - need;

			while(need) {
				ssize_t r = ws_raw_read(wsh, wsh->payload + wsh->rplen, need, WS_BLOCK);

				if (r < 1) {
					/* invalid read - protocol err .. */
					*oc = WSOC_CLOSE;
					return ws_close(wsh, WS_PROTO_ERR);
				}

				wsh->datalen += r;
				wsh->rplen += r;
				need -= r;
			}
			
			if (mask && maskp) {
				ssize_t i;

				for (i = 0; i < wsh->datalen; i++) {
					wsh->payload[i] ^= maskp[i % 4];
				}
			}
			

			if (*oc == WSOC_PING) {
				ws_write_frame(wsh, WSOC_PONG, wsh->payload, wsh->rplen);
				goto again;
			}

			if (frag) {
				goto again;
			}
			

			*(wsh->payload+wsh->rplen) = '\0';
			*data = (uint8_t *)wsh->payload;

			//printf("READ[%ld][%d]-----------------------------:\n[%s]\n-------------------------------\n", wsh->rplen, *oc, (char *)*data);


			return wsh->rplen;
		}
		break;
	default:
		{
			/* invalid op code - protocol err .. */
			*oc = WSOC_CLOSE;
			return ws_close(wsh, WS_PROTO_ERR);
		}
		break;
	}
}
Example #21
0
/* Opens a file and prepares a ftap struct.
   If "do_random" is TRUE, it opens the file twice; the second open
   allows the application to do random-access I/O without moving
   the seek offset for sequential I/O, which is used by Wireshark
   so that it can do sequential I/O to a capture file that's being
   written to as new packets arrive independently of random I/O done
   to display protocol trees for packets when they're selected. */
ftap* ftap_open_offline(const char *filename, int *err, char **err_info,
			gboolean do_random)
{
	int	fd;
	ws_statb64 statb;
	ftap	*fth;
	unsigned int	i;
	gboolean use_stdin = FALSE;
	gchar *extension;

	/* open standard input if filename is '-' */
	if (strcmp(filename, "-") == 0)
		use_stdin = TRUE;

	/* First, make sure the file is valid */
	if (use_stdin) {
		if (ws_fstat64(0, &statb) < 0) {
			*err = errno;
			return NULL;
		}
	} else {
		if (ws_stat64(filename, &statb) < 0) {
			*err = errno;
			return NULL;
		}
	}
	if (S_ISFIFO(statb.st_mode)) {
		/*
		 * Opens of FIFOs are allowed only when not opening
		 * for random access.
		 *
		 * XXX - currently, we do seeking when trying to find
		 * out the file type, so we don't actually support
		 * opening FIFOs.  However, we may eventually
		 * do buffering that allows us to do at least some
		 * file type determination even on pipes, so we
		 * allow FIFO opens and let things fail later when
		 * we try to seek.
		 */
		if (do_random) {
			*err = FTAP_ERR_RANDOM_OPEN_PIPE;
			return NULL;
		}
	} else if (S_ISDIR(statb.st_mode)) {
		/*
		 * Return different errors for "this is a directory"
		 * and "this is some random special file type", so
		 * the user can get a potentially more helpful error.
		 */
		*err = EISDIR;
		return NULL;
	} else if (! S_ISREG(statb.st_mode)) {
		*err = FTAP_ERR_NOT_REGULAR_FILE;
		return NULL;
	}

	/*
	 * We need two independent descriptors for random access, so
	 * they have different file positions.  If we're opening the
	 * standard input, we can only dup it to get additional
	 * descriptors, so we can't have two independent descriptors,
	 * and thus can't do random access.
	 */
	if (use_stdin && do_random) {
		*err = FTAP_ERR_RANDOM_OPEN_STDIN;
		return NULL;
	}

	errno = ENOMEM;
	fth = (ftap *)g_malloc0(sizeof(ftap));

	/* Open the file */
	errno = FTAP_ERR_CANT_OPEN;
	if (use_stdin) {
		/*
		 * We dup FD 0, so that we don't have to worry about
		 * a file_close of wth->fh closing the standard
		 * input of the process.
		 */
		fd = ws_dup(0);
		if (fd < 0) {
			*err = errno;
			g_free(fth);
			return NULL;
		}
#ifdef _WIN32
		if (_setmode(fd, O_BINARY) == -1) {
			/* "Shouldn't happen" */
			*err = errno;
			g_free(fth);
			return NULL;
		}
#endif
		if (!(fth->fh = file_fdopen(fd))) {
			*err = errno;
			ws_close(fd);
			g_free(fth);
			return NULL;
		}
	} else {
		if (!(fth->fh = file_open(filename))) {
			*err = errno;
			g_free(fth);
			return NULL;
		}
	}

	if (do_random) {
		if (!(fth->random_fh = file_open(filename))) {
			*err = errno;
			file_close(fth->fh);
			g_free(fth);
			return NULL;
		}
	} else
		fth->random_fh = NULL;

	/* initialization */
	fth->file_encap = FTAP_ENCAP_UNKNOWN;
	fth->subtype_sequential_close = NULL;
	fth->subtype_close = NULL;
    fth->priv = NULL;

    init_magic_number_open_routines();
	init_heuristic_open_info();
	if (fth->random_fh) {
		fth->fast_seek = g_ptr_array_new();

		file_set_random_access(fth->fh, FALSE, fth->fast_seek);
		file_set_random_access(fth->random_fh, TRUE, fth->fast_seek);
	}

	/* Try all file types that support magic numbers */
	for (i = 0; i < magic_number_open_routines_arr->len; i++) {
		/* Seek back to the beginning of the file; the open routine
		   for the previous file type may have left the file
		   position somewhere other than the beginning, and the
		   open routine for this file type will probably want
		   to start reading at the beginning.

		   Initialize the data offset while we're at it. */
		if (file_seek(fth->fh, 0, SEEK_SET, err) == -1) {
			/* I/O error - give up */
			ftap_close(fth);
			return NULL;
		}

		switch ((*magic_number_open_routines[i])(fth, err, err_info)) {

		case -1:
			/* I/O error - give up */
			ftap_close(fth);
			return NULL;

		case 0:
			/* No I/O error, but not that type of file */
			break;

		case 1:
			/* We found the file type */
			goto success;
		}
	}

	/* Does this file's name have an extension? */
	extension = get_file_extension(filename);
	if (extension != NULL) {
		/* Yes - try the heuristic types that use that extension first. */
		for (i = 0; i < heuristic_open_info_arr->len; i++) {
			/* Does this type use that extension? */
			if (heuristic_uses_extension(i, extension)) {
				/* Yes. */
				if (file_seek(fth->fh, 0, SEEK_SET, err) == -1) {
					/* I/O error - give up */
					g_free(extension);
					ftap_close(fth);
					return NULL;
				}

				switch ((*heuristic_open_info[i].open_routine)(fth,
				    err, err_info)) {

				case -1:
					/* I/O error - give up */
					g_free(extension);
					ftap_close(fth);
					return NULL;

				case 0:
					/* No I/O error, but not that type of file */
					break;

				case 1:
					/* We found the file type */
					g_free(extension);
					goto success;
				}
			}
		}

		/* Now try the ones that don't use it. */
		for (i = 0; i < heuristic_open_info_arr->len; i++) {
			/* Does this type use that extension? */
			if (!heuristic_uses_extension(i, extension)) {
				/* No. */
				if (file_seek(fth->fh, 0, SEEK_SET, err) == -1) {
					/* I/O error - give up */
					g_free(extension);
					ftap_close(fth);
					return NULL;
				}

				switch ((*heuristic_open_info[i].open_routine)(fth,
				    err, err_info)) {

				case -1:
					/* I/O error - give up */
					g_free(extension);
					ftap_close(fth);
					return NULL;

				case 0:
					/* No I/O error, but not that type of file */
					break;

				case 1:
					/* We found the file type */
					g_free(extension);
					goto success;
				}
			}
		}
		g_free(extension);
	} else {
		/* No - try all the heuristics types in order. */
		for (i = 0; i < heuristic_open_info_arr->len; i++) {
			if (file_seek(fth->fh, 0, SEEK_SET, err) == -1) {
				/* I/O error - give up */
				ftap_close(fth);
				return NULL;
			}

			switch ((*heuristic_open_info[i].open_routine)(fth,
			    err, err_info)) {

			case -1:
				/* I/O error - give up */
				ftap_close(fth);
				return NULL;

			case 0:
				/* No I/O error, but not that type of file */
				break;

			case 1:
				/* We found the file type */
				goto success;
			}
		}
	}

    /* Well, it's not one of the types of file we know about. */
	ftap_close(fth);
	*err = FTAP_ERR_FILE_UNKNOWN_FORMAT;
	return NULL;

success:
	fth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
	buffer_init(fth->frame_buffer, 1500);

	return fth;
}