Etablish DDP connection between Meteor Server and C app - c

I'm developing a Meteor application with two client, one is in JavaScript and the other one is in C.
I'm actually trying to connect my C app to the server using websocket. I'm using the library nopoll for the websocket (http://www.aspl.es/nopoll/html/index.html) and jansson for the JSON serialization (http://www.digip.org/jansson/).
I read the DDP Specification (https://github.com/meteor/meteor/blob/devel/packages/ddp/DDP.md) and this brief (but good) explanation (https://meteorhacks.com/introduction-to-ddp.html).
Here is the code is the websocket initialization
int main(int ac, char** av)
{
// Create noPoll context
noPollCtx* ctx = nopoll_ctx_new();
if (! ctx)
{
puts("Error creating nopoll context");
return EXIT_FAILURE;
}
puts("Context created");
// Create connection
noPollConn* conn = nopoll_conn_new(ctx, "localhost", "3000", NULL, "/websocket", NULL, NULL);
if (! nopoll_conn_is_ok(conn))
{
puts("Error creating new connection");
return EXIT_FAILURE;
}
puts("Connection created");
// Wait until connection is ready
if (! nopoll_conn_wait_until_connection_ready(conn, 5))
{
puts("Connection timeout");
return EXIT_FAILURE;
}
puts("Connection ready");
connection_to_DDP_server(conn);
send_msg_loop(conn);
nopoll_ctx_unref(ctx);
return EXIT_SUCCESS;
}
And the connection to the Meteor server
void connection_to_DDP_server(noPollConn* conn)
{
int ret = 0;
json_t* connect = json_pack("{s:s,s:s,s:[s]}",
"msg", "connect",
"version", "1",
"support", "1");
char* content = json_dumps(connect, JSON_COMPACT);
printf("DDP Connect - JSON string = %s\n", content);
ret = nopoll_conn_send_text(conn, content, strlen(content) + 1);
if (ret == -1)
{
puts("DDP Connect fail");
exit(EXIT_FAILURE);
}
printf("%i bytes written\n", ret);
}
I have this error on the server console :
I20141201-08:54:13.498(1)? Discarding message with invalid JSON
{"msg":"connect","support":["1"],"version":"1"}
I don't understand why... I am sending valid JSON and referring to the DDP doc I am doing things well (at least I think so...).

The problem was I was sending 1 character too much than normally expected. Now, I get a :
{"msg":"connected","session":"HupHMhcFK4avy4vwg"}
to tell me that i'm connected.
I was the sending the '\0' and the JSON parser don't recognize it.

Related

Getting SSL_connect segmentation fault in Linux application

I am preparing a sample C application to stream file from one remote(FTP) location to another remote location(HTTP). In the application I want to download file using curl API & uploading the downloaded content using ssl API. I am getting segmentation-fault in SSL_connect(), Here is the init code,
SSL* ssl = NULL;//Global variable
SSL_CTX* ssl_ctx = NULL;//Global variable
/* initialize OpenSSL first */
SSL_library_init();
SSL_load_error_strings();
do
{
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
if (!ssl_ctx)
{
fprintf(stderr, "Failed to SSL_CTX_new\n");
break;
}
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
ssl = SSL_new(ssl_ctx);
if (!ssl)
{
fprintf(stderr, "Failed to SSL_new\n");
break;
}
if (SSL_set_fd(ssl, sock) != 1)
{
fprintf(stderr, "Failed to SSL_set_fd\n");
break;
}
int err = SSL_connect(ssl);
if (err != 1)
{
fprintf(stderr, "Failed to SSL_connect\n");
break;
}
return_code = 0;
} while(0);
Here 'sock' is open socket connected with remote opened before this call.
I verified pointers passing & type-casting, Looks good to me.
Can anyone suggest any break-through?
Thanks in advance.
Try running gdb and set up a breakpoint at the line int err = SSL_connect(ssl);, check if ss1 is correctly initialized. Here is a simple tutorial on how to use gdb: https://cseweb.ucsd.edu/classes/fa09/cse141/tutorial_gcc_gdb.html

libssh tunnel echoing input

I've created my own SSH reverse tunnel using libssh by following the tutorials at http://api.libssh.org/master/libssh_tutorial.html and piecing things together from various other samples. However, now, all I get is the client echoing back whatever is inputted via the tunnel connection. I'm trying to get to the point where I can execute commands through the reverse tunnel (ex: ls -al).
The reverse tunnel (initiated on the client side):
int reverse_loop(ssh_session session){
ssh_channel channel;
int rc;
int nbytes, nwritten;
char buf[256];
int port = 0;
rc = ssh_channel_listen_forward(session, NULL, 43434, NULL);
if (rc != SSH_OK){
fprintf(stderr, "Error opening remote port %s\n", ssh_get_error(session));
return rc;
}
channel = ssh_channel_accept_forward(session, 60000, &port);
if (channel == NULL){
fprintf(stderr, "Error waiting for incoming connection: %s\n", ssh_get_error(session));
return SSH_ERROR;
}
while(1){
printf("In loop\n");
nbytes = ssh_channel_read(channel, buf, sizeof(buf), 0);
if (nbytes < 0){
fprintf(stderr, "Error reading incoming data: %s\n", ssh_get_error(session));
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
printf("read channel\n");
if (nbytes > 0){
nwritten = ssh_channel_write(channel, buf, nbytes);
if (nwritten != nbytes){
fprintf(stderr, "Error sending answer: %s\n", ssh_get_error(session));
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
printf("Wrote channel\n");
}
printf("sent answer!\n");
}
// close_channel
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
return SSH_OK;
}
Running this, the reverse session is initiated. So, from the SSH server, I can run:
> nc localhost 43434
ls (this is what I sent)
ls (this is what I receive)
pwd (this is what I sent)
pwd (this is what I receive)
Then on the client side, I see this output:
In loop
read channel
Wrote channel
sent answer!
In loop
What I'm looking for are the actual results of running ls or pwd (or whatever system command the user inputs, not the echo. Can anyone direct me on the step that I missed to do this?
Thanks!

Seems like pthread_create is overriding previous threads

I'm trying to write an IRC type chat client which has clients that can connected to a server. I'm trying to get it to work locally atm (Using FIFOS instead of sockets).
I've run into the following issue which I can't seem to solve:
After accepting a new client connection, I want to create a new thread for that client (on the server) that'll handle inputs from that client.
To do this I have the following piece of code (the full code is at the bottom):
while(1) {
.
.
.
if (pthread_create(&thread, NULL, client_handler, &new_client) != 0)
printf("Couldn't create a thread to listen to the client.... Not ok \n");
}
This works fine with 1 connected client.
The moment I try to connect another client it seems the previous thread that executed the method client_handler stopped running.
I know this because the server stops accepting input from that client, but the new thread works just fine (the one that handles the newly connected client).
I was wondering if my methodology was wrong or if I'm not using the pthread_create correctly.
Has anyone got any suggestions?
void server_listen() {
Client new_client;
ClientNode temp;
buffint client_name_length;
char client_name[CLIENT_NAME_SIZE];
char fifo_in[FIFO_NAME_SIZE], fifo_out[FIFO_NAME_SIZE];
buffint client_pid;
char ack[4] = "/ack";
char inuse[6] = "/inuse";
pthread_t thread;
buffint length;
ClientNode it;
buffint message_length;
char message[MESSAGE_LENGTH];
pthread_mutexattr_t attr;
while (1) {
memset(client_name, 0, CLIENT_NAME_SIZE);
client_name_length.data =0;
if (read_helper(irc_server.server_fifo, client_name_length.buff,
sizeof(int)) == -1)
return; /* error */
if (read_helper(irc_server.server_fifo, client_pid.buff, sizeof(int))
== -1)
return; /* error */
if (read_helper(irc_server.server_fifo, client_name, client_name_length.data) == -1)
return; /* error */
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ERRORCHECK_NP);
pthread_mutex_init(&new_client.fifo_in_lock, &attr);
printf("Reading from a new client, with name: %s\n", client_name);
new_client.pid = client_pid.data;
strncpy(new_client.name, client_name, client_name_length.data);
new_client.name_length = client_name_length.data;
sprintf(fifo_in, "fifo-%d-in", client_pid.data);
sprintf(fifo_out, "fifo-%d-out", client_pid.data);
new_client.fifo_in = open(fifo_in, O_WRONLY);
if (new_client.fifo_in == -1)
return; /* error */
new_client.fifo_out = open(fifo_out, O_RDONLY);
if (new_client.fifo_out == -1)
return; /* error */
read_lock();
temp = client_exists_by_name(&irc_server.clients, client_name, client_name_length.data);
read_unlock();
if (temp != NULL) {
pthread_mutex_lock(&new_client.fifo_in_lock);
length.data = 6;
if (write_helper(new_client.fifo_in, length.buff, sizeof(int))
== -1) {
//TODO: What do we do if writing to the fifo_out failed?
printf( "Writing to the fifo-out failed for some unknown reason \n");
return;
}
if (write_helper(new_client.fifo_in, inuse, length.data) == -1) {
//TODO: What do we do if writing to the fifo_out failed?
printf( "Writing to the fifo-out failed for some unknown reason \n");
return;
}
pthread_mutex_unlock(&new_client.fifo_in_lock);
continue;
}
write_lock();
insert_node(&irc_server.clients, new_client);
write_unlock();
length.data = 4;
pthread_mutex_lock(&new_client.fifo_in_lock);
if (write_helper(new_client.fifo_in, length.buff, sizeof(int)) == -1) {
//TODO: What do we do if writing to the fifo_out failed?
printf("Writing to the fifo-out failed for some unknown reason \n");
return;
}
if (write_helper(new_client.fifo_in, ack, length.data) == -1) {
//TODO: What do we do if writing to the fifo_out failed?
printf("Writing to the fifo-out failed for some unknown reason \n");
return;
}
pthread_mutex_unlock(&new_client.fifo_in_lock);
foreach(it, irc_server.clients){
pthread_mutex_lock(&it->client.fifo_in_lock);
strncpy(message, new_client.name, new_client.name_length);
strncat(message, " joined the chat", sizeof(" joined the chat"));
message_length.data = sizeof(" joined the chat") + new_client.name_length;
if (write_helper(it->client.fifo_in, message_length.buff, sizeof(int)) == -1) {
//TODO: What do we do if writing to the fifo_out failed?
printf("writing to the fifo_in a public message ERROR1 \n");
return;
}
if (write_helper(it->client.fifo_in, message, message_length.data) == -1) {
//TODO: What do we do if writing to the fifo_out failed?
printf("writing to the fifo_in a public message ERROR2 \n");
return;
}
pthread_mutex_unlock(&it->client.fifo_in_lock);
memset(message, 0, MESSAGE_LENGTH);
message_length.data = 0;
}
if (pthread_create(&thread, NULL, client_handler, &new_client) != 0)
printf("Couldn't create a thread to listen to the client.... Not ok \n");
if (pthread_create(&thread, NULL,client_handler1 ,&new_client ) != 0)
printf("Couldn't create a thread to listen to the client.... Not ok \n");
print_clients();
}
}
It looks like you're sharing a single instance of new_client between all the threads in the server. A call to pthread_create() doesn't magically copy new_client. So every thread you create is using the same new_client. So when your master thread fills in values for a second client, the thread handling the first client tries to use those too.
Allocate a new new_client for each client, fill in the values and pass that into pthread_create(). You'll also need a per-client variable for the first parameter in pthread_create().
Other things - you're seemingly passing raw binary data between your client and server, things like string length integers. That kind of thing is going to cause you a whole pile of woe as soon as you have to start doing clients for different OSes. I strongly recommend you adopt a serialisation technology, preferably ASN.1 (not free but really robust) or Google Protocol Buffers (free but not as rich or robust).
if (pthread_create(&thread, NULL,client_handler ,&new_client ) != 0)
...
if (pthread_create(&thread, NULL,client_handler1 ,&new_client ) != 0)
Why you are using same pthread_t variable every time? You can't use same thread variable. Prefer to use an array of pthread_t like this:
pthread_t thread[2];
if (pthread_create(&thread[0], NULL, client_handler, &new_client ) != 0)
...
if (pthread_create(&thread[1], NULL, client_handler1, &new_client ) != 0)

SCP functionality in C. library list: libCurl, libssh or libssh2

EDIT
I had a problem a while ago writing a program in C which utilizes scp to transfer and download files to a server. The program had to be written for windows. Initially I attempted to use the libCurl library which then I encountered different problems and it didn't work well. After switching to libssh and the issue was fixed.
I'm posting a segment of my sample code which downloads a file from a remote server. hopefully this could be helpful to anyone who lands here.
int scp_recv_file(ssh_session in_session,
char * in_remotefile, char * in_localfile)
{
ssh_scp t_scp = NULL;
int t_rc, t_filesize, t_filemode = -1;
char *t_filename, *t_buffer;
t_scp = ssh_scp_new
(in_session, SSH_SCP_READ | SSH_SCP_RECURSIVE, in_remotefile);
if (t_scp == NULL)
{
fprintf(stderr, "Error allocating scp session: %s\n",
ssh_get_error(in_session));
return SSH_ERROR;
}
t_rc = ssh_scp_init(t_scp);
if (t_rc != SSH_OK)
{
fprintf(stderr, "Error initializing scp session: %s\n",
ssh_get_error(in_session));
ssh_scp_free(t_scp);
return t_rc;
}
//create ssh pull a file request
t_rc = ssh_scp_pull_request(t_scp);
if (t_rc != SSH_SCP_REQUEST_NEWFILE)
{
fprintf(stderr, "Error receiving information about file: %s\n",
ssh_get_error(in_session));
return SSH_ERROR;
}
t_filesize = ssh_scp_request_get_size(t_scp);
t_filename = strdup(ssh_scp_request_get_filename(t_scp));
t_filemode = ssh_scp_request_get_permissions(t_scp);
printf("Receiving file %s, size %d, permisssions 0%o\n",
t_filename, t_filesize, t_filemode);
t_buffer = malloc(t_filesize);
if (t_buffer == NULL)
{
fprintf(stderr, "Memory allocation error\n");
return SSH_ERROR;
}
ssh_scp_accept_request(t_scp);
t_rc = ssh_scp_read(t_scp, t_buffer, t_filesize);
if (t_rc == SSH_ERROR)
{
fprintf(stderr, "Error receiving file data: %s\n",
ssh_get_error(in_session));
free(t_buffer);
return t_rc;
}
printf("Done\n");
//write buffer to file
writeToFile(in_localfile, t_buffer, t_filesize);
//write(1, buffer, size);
//free allocated memory
free(t_buffer);
free(t_filename);
t_rc = ssh_scp_pull_request(t_scp);
if (t_rc != SSH_SCP_REQUEST_EOF)
{
fprintf(stderr, "Unexpected request: %s\n",
ssh_get_error(in_session));
return SSH_ERROR;
}
//close scp and free
ssh_scp_close(t_scp);
ssh_scp_free(t_scp);
return SSH_OK;
}
Switched to lilbssh. You can manage the scp stages manually and works ok. However, I don't know if libssh2 is better or not. Any comments?

2-way communication with C sockets

I am trying to have 2 way communication running between C sockets. For having the sockets set up, I was following the instructions on this link (http://www.linuxhowtos.org/C_C++/socket.htm) and everything worked fine. Sending messages from the client to the server worked perfectly.
However, I would also like the ability of the server to send response messages back to the client. How is this accomplished? If I set up a client and server connection at both ends, one of them cannot bind.
edit more code. Currently, I've used this style of sockets and put them into c++ code, just because that's my familiarity. Ignore the object oriented-ness.
//main call
if (server)
{
Connection recv(true, "servername");
recv.GetMsg();
recv.SendMsg("test", 4);
}
else // client
{
Connection snd(false, "servername");
snd.GetMsg();
snd.SendMsg("this is a test", 14);
}
And inside the Connection class,
void SendMsg(char *msg, int msg_length)
{
send(some_socket, msg, msg_length, 0);
};
void GetMsg()
{
recvd = recv(opponent_socket, buffer, sizeof(buffer), 0);
buffer[recvd] = '\0';
cout << "Printing msg: " << buffer << endl;
};
Connection::Connection(bool isserver, char *servername)
{
is_server = isserver;
server = servername;
opponent_socket = 0;
some_socket = socket(PF_INET, SOCK_STREAM, 0);
if (some_socket < 0)
{
cout << "Connection failed.\n" << endl;
exit(-1);
}
if (is_server)
{
AddrSetupServer(); // standard calls here. Pretty well what's shown in link provided
BindServer();
ListenServer();
WaitConnectionServer();
}
else
{
AddrSetupClient();
ConnectClient();
}
};
Once you have a connection, it is bidirectional; simply send your response over the socket.

Resources