DDP server writen in C library


#1

Hi !
I need to connect my database (sybase), linux & written in C (and Clip) app with new client interface that i would like to seen in meteor technology. Application is to big to translate everything into new technology at once - and it has few customers, that can’t do theyre job if it takes to much time.
So - first & most important stuff for now is not change the great working engine and database technology that is very efficient - but move this all into background and do new user interface.
Best way in my mind is change existing C application into DDP METEOR server. I can write all client side code in meteor/nodejs www site and use collection and RPC. Client side meteor app should use my old-app like DDP server.

After I had a look into google, stackoverflow, DDP definition and meteor forum - a found nopoll and janssen library and write server and client sample working DDP code in C in Debian squeeze environment.
Pretty soon everything started to work. I attache code bellow.

PROBLEM is, that everything works good (websocket communication and encoding/decoding JSON messages…) until i try to use real meteor DDP.CONNECT method. That connect to C-ddp server, but does’nt do nothing else.
There is very little DDP documentation on internet.

maybe someone did something like that and can help?

============================
server:

#include <nopoll.h>
#include <stdio.h>
#include <jansson.h>

void listener_on_message (noPollCtx *ctx, noPollConn *conn, noPollMsg *pool_msg, noPollPtr user_data) {
	printf("msg befour received: %s\n",nopoll_msg_get_payload(pool_msg));
	int i=0;
	if (nopoll_msg_is_final(pool_msg)){
		printf("msg received: %s\n",nopoll_msg_get_payload(pool_msg));
		
		//dekodowanie pool_msg:
		json_error_t error;
		json_t *root=json_loads(nopoll_msg_get_payload(pool_msg),0,&error);
		if (!root){
			printf("listener_on_message: blad-root w linii %d: %s\n",error.line,error.text);
			return;
		}
		json_t *msg=NULL;
		if(!(msg=json_object_get(root,"msg")) || !json_is_string(msg)){
			printf("listener_on_message: blad-brak pola msg\n");
			json_decref(root);
			return;
		}


		//PING-----------------------------------------------------------------------------------------------
		if(!strcmp("ping",json_string_value(msg))){
			printf("msg: ping\n");
			const char *id_str=NULL;
			json_t *id=json_object_get(root,"id");
			if(id && json_is_string(id)){
				id_str=json_string_value(id);
			}
			//return
			char *content=NULL;
			if(id_str){
				content=json_dumps(json_pack("{s:s,s:s}",
					"msg", "pong",
					"id", id_str),JSON_COMPACT);
			} else {
				content=json_dumps(json_pack("{s:s}",
					"msg", "pong"),JSON_COMPACT);
			}
			if(nopoll_conn_send_text(conn,content,strlen(content))!=strlen(content)){
				printf("listener_on_message, msg=ping: blad-nie udalo sie odeslac msg=pong\n");
				return;
			}
			printf("listener_on_message, msg=ping: OK, odeslano msg=pong\n");
			json_decref(root);
			json_decref(id);
			return;
		}


		//pobranie ID sesji:
		json_t *session=json_object_get(root,"session");
		if(!session || !json_is_string(session)){
			printf("listener_on_message, msg=connect: blad-brak pola session lub nie jest typu string\n");
			json_decref(root);
			json_decref(session);
			return;
		}
		
		//obsluga wiadomosci:
		
		//CONNECT-----------------------------------------------------------------------------------------------
		if(!strcmp("connect",json_string_value(msg))){
			printf("msg: connect\n");
			json_t *version=json_object_get(root,"version");
			if(version){
				if (!json_is_string(version) || atoi(json_string_value(version))<1){
					printf("listener_on_message, msg=connect: blad-nieprawidlowe pole version\n");
					json_decref(root);
					json_decref(session);
					json_decref(version);
					return;
				}
			}
			json_t *support=json_object_get(root,"support");
			if(support){
				if(!json_is_array(support)){
					printf("listener_on_message, msg=connect: blad-otrzymano pole support ktore nie jest tablica");
					json_decref(root);
					json_decref(session);
					json_decref(version);
					json_decref(support);
					return;
				}
				int i;
				for(i=0; i<json_array_size(support);i++){
					json_t *el=json_array_get(support,i);
					if(!el || !json_is_string(el)){
						printf("listener_on_message, msg=connect: blad-nie rozkodowano wartości z tablicy support\n");
						json_decref(root);
						json_decref(session);
						json_decref(version);
						json_decref(support);
						json_decref(el);
						return;
					}
					if(atoi(json_string_value(el))==1 && atoi(json_string_value(version))!=1){
						printf("listener_on_message, msg=connect: blad-połączenie z version=%s, podczas gdy jest support=%s\n",
							json_string_value(version), json_string_value(el));
						json_decref(root);
						json_decref(version);
						json_decref(support);
						json_decref(el);
						
						//zbudowanie odpowiedzi:
						char *content=json_dumps(json_pack("{s:s,s:s,s:s}",
							"session", json_string_value(session),
							"msg","failed",
							"version", "1"),JSON_COMPACT);
						if(nopoll_conn_send_text(conn,content,strlen(content))==-1){
							printf("listener_on_message, msg=connect: blad-nie udalo sie odeslac msg=failed\n");
							return;
						}
						printf("msg=connect, odeslano msg=failed\n");
						json_decref(session);
						return;
					}
					json_decref(el);
				}
			}
			//potwierdzenie połączenia:
			char *content=json_dumps(json_pack("{s:s,s:s}",
				"session", json_string_value(session),
				"msg","connected"),JSON_COMPACT);
			if(nopoll_conn_send_text(conn,content,strlen(content))!=strlen(content)){
				printf("listener_on_message, msg=connect: blad-nie udalo sie odeslac msg=connected\n");
				return;
			}
			printf("listener_on_message, msg=connect: OK, odeslano msg=connected(%s)\n",json_string_value(session));
			json_decref(root);
			json_decref(version);
			json_decref(session);
			json_decref(support);
			return;
		}

		
		
		// if (!json_is_array(json_root)){
		// 	printf("listener_on_message: blad-json_root nie jest tablicą\n");
		//
		// 	//odczytujemy pola:
		// 	json_t *json_msg=json_object_get(json_root,"msg");
		// 	if (!json_msg){
		// 		printf("listener_on_message: blad-odczyt msg w linii %d: %s\n",error.line,error.text);
		// 		json_decref(json_root);
		// 		return;
		// 	}
		// 	if(json_is_string(json_msg)){
		// 		printf("json_msg=%s\n",json_string_value(json_msg))				;
		//
		// 	} else {
		// 		printf("listener_on_message: blad-json_msg nie jest typu string\n");
		// 		json_decref(json_root);
		// 		return;
		// 	}
		// 	if(!strcmp(json_string_value(json_msg),"connect")){
		// 		printf("otrzymano msg=connect\n");
		// 		json_decref(json_msg);
		// 	}
		//
		// 	json_decref(json_root);
		// 	return;
		// }
		// for(i=0; i<json_array_size(json_root); i++){
		// 	json_t *tmp=json_array_get(json_root,i);
		// 	if (tmp){
		// 		if (json_is_string(tmp)){
		// 			printf("element %d (string): %s\n",i,json_string_value(tmp));
		// 		}
		// 		else if (json_is_object(tmp)){
		// 			printf("element %d (object)\n",i);
		// 		}
		// 	}
		// 	json_decref(tmp);
		// }
		
		json_decref(root);
	}
	
        // // print the message (for debugging purposes) and reply
        // printf ("Listener received (size: %d, ctx refs: %d): (first %d bytes, fragment: %d) '%s'\n",
        //         nopoll_msg_get_payload_size (msg),
        //         nopoll_ctx_ref_count (ctx), 5, nopoll_msg_is_fragment (msg), "example");
    
        // reply to the message
        nopoll_conn_send_text (conn, "Message received", 16);
  
        return;
}

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 a listener to receive connections on port 1234
	noPollConn * listener = nopoll_listener_new (ctx, "0.0.0.0", "1234");
	if (! nopoll_conn_is_ok (listener)) {
	     // some error handling here
		printf("nopoll_listener_new: error..\n");
	}
	// now set a handler that will be called when a message (fragment or not) is received
	nopoll_ctx_set_on_msg (ctx, listener_on_message, NULL);

	// now call to wait for the loop to notify events 
	nopoll_loop_wait (ctx, 0);

        nopoll_ctx_unref(ctx);
        return EXIT_SUCCESS;
}

and client like to test this:

#include <nopoll.h>
#include <stdio.h>
#include <jansson.h>

void connection_to_DDP_server(noPollConn* conn)
{
  int ret = 0;
  json_t* connect = json_pack("{s:s,s:s,s:s,s:[s]}",
	  "session","asfgaiuysdfaiuysdgfiayusdf",
        "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));
  if (ret == -1)
  {
    puts("DDP Connect fail");
    exit(EXIT_FAILURE);
  }
  printf("%i bytes written\n", ret);

  connect = json_pack("{s:s,s:s}",
	  "id","12312312",
        "msg", "ping");
  content = json_dumps(connect, JSON_COMPACT);
  printf("DDP Connect - JSON string = %s\n", content);
  ret = nopoll_conn_send_text(conn, content, strlen(content));
  if (ret == -1)
  {
    puts("DDP Connect fail");
    exit(EXIT_FAILURE);
  }
  printf("%i bytes written\n", ret);


}

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);
  noPollConn* conn = nopoll_conn_new(ctx, "localhost", "1234", 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");
  
  // int i;
  // for(i=0; i<100; i++)
  	connection_to_DDP_server(conn);
  
  // send_msg_loop(conn);
  
  nopoll_ctx_unref(ctx);
  return EXIT_SUCCESS;
}