diff --git a/apps/sam/c/inc/sam.h b/apps/sam/c/inc/sam.h index 656ef978abfdaa86bd559b97cf2ccc4f19ecbeb3..5069e9ba93faebc9f69900fb70bc8047151ec8d4 100644 --- a/apps/sam/c/inc/sam.h +++ b/apps/sam/c/inc/sam.h @@ -38,9 +38,11 @@ extern "C" { #include <stddef.h> #include <stdint.h> + /* * Lengths */ + /* The maximum length a SAM command can be */ #define SAM_CMD_LEN 128 /* The maximum size of a single datagram packet */ @@ -49,18 +51,22 @@ extern "C" { #define SAM_LOGMSG_LEN 256 /* The longest `name' arg for the naming lookup callback */ #define SAM_NAME_LEN 256 -/* The max size of a single stream packet */ +/* The maximum size of a single stream packet */ #define SAM_STREAM_PAYLOAD_MAX (32 * 1024) /* The length of a base 64 public key - it's actually 516, but +1 for '\0' */ #define SAM_PUBKEY_LEN 517 -/* A public key SAM command's length */ +/* The maximum length of a SAM command with a public key */ #define SAM_PKCMD_LEN (SAM_PUBKEY_LEN + SAM_CMD_LEN) +/* The maximum size of a single raw packet */ +#define SAM_RAW_LEN (32 * 1024) /* The maximum length a SAM non-data reply can be */ #define SAM_REPLY_LEN 1024 + /* - * Shorten some standard variable types + * Some LibSAM variable types */ + typedef signed char schar_t; typedef unsigned char uchar_t; typedef unsigned int uint_t; @@ -102,57 +108,62 @@ typedef enum { /* see sam_strerror() for detailed descriptions of these */ SAM_TOO_BIG } samerr_t; + /* * Public functions */ /* SAM controls - sessions */ -extern sam_sess_t *sam_session_init(sam_sess_t *session); -extern void sam_session_free(sam_sess_t **session); +sam_sess_t *sam_session_init(sam_sess_t *session); +void sam_session_free(sam_sess_t **session); /* SAM controls - connection */ -extern bool sam_close(sam_sess_t *session); -extern samerr_t sam_connect(sam_sess_t *session, const char *samhost, - uint16_t samport, const char *destname, sam_conn_t style, - uint_t tunneldepth); +bool sam_close(sam_sess_t *session); +samerr_t sam_connect(sam_sess_t *session, const char *samhost, + uint16_t samport, const char *destname, sam_conn_t style, + uint_t tunneldepth); /* SAM controls - utilities */ -extern void sam_naming_lookup(sam_sess_t *session, const char *name); -extern bool sam_read_buffer(sam_sess_t *session); -extern const char *sam_strerror(samerr_t code); +void sam_naming_lookup(sam_sess_t *session, const char *name); +bool sam_read_buffer(sam_sess_t *session); +const char *sam_strerror(samerr_t code); /* SAM controls - callbacks */ -extern void (*sam_diedback)(sam_sess_t *session); -extern void (*sam_logback)(char *str); -extern void (*sam_namingback)(char *name, sam_pubkey_t pubkey, - samerr_t result); +void (*sam_diedback)(sam_sess_t *session); +void (*sam_logback)(char *str); +void (*sam_namingback)(char *name, sam_pubkey_t pubkey, samerr_t result); /* Stream commands */ -extern void sam_stream_close(sam_sess_t *session, sam_sid_t stream_id); -extern sam_sid_t sam_stream_connect(sam_sess_t *session, - const sam_pubkey_t dest); -extern samerr_t sam_stream_send(sam_sess_t *session, sam_sid_t stream_id, - const void *data, size_t size); +void sam_stream_close(sam_sess_t *session, sam_sid_t stream_id); +sam_sid_t sam_stream_connect(sam_sess_t *session, const sam_pubkey_t dest); +samerr_t sam_stream_send(sam_sess_t *session, sam_sid_t stream_id, + const void *data, size_t size); /* Stream commands - callbacks */ -extern void (*sam_closeback)(sam_sess_t *session, sam_sid_t stream_id, - samerr_t reason); -extern void (*sam_connectback)(sam_sess_t *session, sam_sid_t stream_id, - sam_pubkey_t dest); -extern void (*sam_databack)(sam_sess_t *session, sam_sid_t stream_id, - void *data, size_t size); -extern void (*sam_statusback)(sam_sess_t *session, sam_sid_t stream_id, - samerr_t result); +void (*sam_closeback)(sam_sess_t *session, sam_sid_t stream_id, + samerr_t reason); +void (*sam_connectback)(sam_sess_t *session, sam_sid_t stream_id, + sam_pubkey_t dest); +void (*sam_databack)(sam_sess_t *session, sam_sid_t stream_id, + void *data, size_t size); +void (*sam_statusback)(sam_sess_t *session, sam_sid_t stream_id, + samerr_t result); /* Stream send queue (experimental) */ -extern void sam_sendq_add(sam_sess_t *session, sam_sid_t stream_id, - sam_sendq_t **sendq, const void *data, size_t dsize); -extern void sam_sendq_flush(sam_sess_t *session, sam_sid_t stream_id, - sam_sendq_t **sendq); +void sam_sendq_add(sam_sess_t *session, sam_sid_t stream_id, + sam_sendq_t **sendq, const void *data, size_t dsize); +void sam_sendq_flush(sam_sess_t *session, sam_sid_t stream_id, + sam_sendq_t **sendq); /* Datagram commands */ -extern samerr_t sam_dgram_send(sam_sess_t *session, const sam_pubkey_t dest, - const void *data, size_t size); - +samerr_t sam_dgram_send(sam_sess_t *session, const sam_pubkey_t dest, + const void *data, size_t size); /* Datagram commands - callbacks */ -extern void (*sam_dgramback)(sam_sess_t *session, sam_pubkey_t dest, - void *data, size_t size); +void (*sam_dgramback)(sam_sess_t *session, sam_pubkey_t dest, void *data, + size_t size); + +/* Raw commands */ +samerr_t sam_raw_send(sam_sess_t *session, const sam_pubkey_t dest, + const void *data, size_t size); +/* Raw commands - callbacks */ +void (*sam_rawback)(sam_sess_t *session, void *data, size_t size); + #ifdef __cplusplus } diff --git a/apps/sam/c/src/sam.c b/apps/sam/c/src/sam.c index 820811b8047263e7e9e23edf975856196db8d12c..33243b6886eb0c20b0e36db1f64513f757b16d9f 100644 --- a/apps/sam/c/src/sam.c +++ b/apps/sam/c/src/sam.c @@ -55,28 +55,40 @@ static ssize_t sam_write(sam_sess_t *session, const void *buf, size_t n); * Callback functions * Note: if you add a new callback be sure to check for non-NULL in sam_connect */ + /* a peer closed the connection */ void (*sam_closeback)(sam_sess_t *session, sam_sid_t stream_id, samerr_t reason) = NULL; + /* a peer connected to us */ void (*sam_connectback)(sam_sess_t *session, sam_sid_t stream_id, sam_pubkey_t dest) = NULL; + /* a peer sent some stream data (`data' MUST be freed) */ void (*sam_databack)(sam_sess_t *session, sam_sid_t stream_id, void *data, size_t size) = NULL; + /* a peer sent some datagram data (`data' MUST be freed) */ void (*sam_dgramback)(sam_sess_t *session, sam_pubkey_t dest, void *data, size_t size) = NULL; + /* we lost the connection to the SAM host */ void (*sam_diedback)(sam_sess_t *session) = NULL; + /* logging callback */ void (*sam_logback)(char *str) = NULL; + /* naming lookup reply - `pubkey' will be NULL if `result' isn't SAM_OK */ void (*sam_namingback)(char *name, sam_pubkey_t pubkey, samerr_t result) = NULL; + /* our connection to a peer has completed */ void (*sam_statusback)(sam_sess_t *session, sam_sid_t stream_id, samerr_t result) = NULL; +/* a peer sent some raw data (`data' MUST be freed) */ +void (*sam_rawback)(sam_sess_t *session, void *data, size_t size) = NULL; + + /* * Closes the connection to the SAM host * @@ -155,7 +167,11 @@ samerr_t sam_connect(sam_sess_t *session, const char *samhost, uint16_t samport, return SAM_CALLBACKS_UNSET; } } else if (style == SAM_RAW) { - abort(); /* not implemented yet */ + if (sam_diedback == NULL || sam_logback == NULL + || sam_namingback == NULL || sam_rawback == NULL) { + SAMLOGS("Please set callback functions before connecting"); + return SAM_CALLBACKS_UNSET; + } } else { SAMLOGS("Unknown connection style"); return SAM_BAD_STYLE; @@ -295,6 +311,7 @@ static void sam_parse(sam_sess_t *session, char *s) #define SAM_NAMING_REPLY_OK "NAMING REPLY RESULT=OK" #define SAM_NAMING_REPLY_IK "NAMING REPLY RESULT=INVALID_KEY" #define SAM_NAMING_REPLY_KNF "NAMING REPLY RESULT=KEY_NOT_FOUND" +#define SAM_RAW_RECEIVED_REPLY "RAW RECEIVED" #define SAM_STREAM_CLOSED_REPLY "STREAM CLOSED" #define SAM_STREAM_CONNECTED_REPLY "STREAM CONNECTED" #define SAM_STREAM_RECEIVED_REPLY "STREAM RECEIVED" @@ -305,6 +322,10 @@ static void sam_parse(sam_sess_t *session, char *s) #define SAM_STREAM_STATUS_REPLY_IK "STREAM STATUS RESULT=INVALID_KEY" #define SAM_STREAM_STATUS_REPLY_TO "STREAM STATUS RESULT=TIMEOUT" + /* + * TODO: add raw parsing + */ + if (strncmp(s, SAM_DGRAM_RECEIVED_REPLY, strlen(SAM_DGRAM_RECEIVED_REPLY)) == 0) { char *p; @@ -518,6 +539,42 @@ static void sam_parse(sam_sess_t *session, char *s) return; } +/* + * Sends data to a destination in a raw packet + * + * dest - base 64 destination of who we're sending to + * data - the data we're sending + * size - the size of the data + * + * Returns: SAM_OK on success + */ +samerr_t sam_raw_send(sam_sess_t *session, const sam_pubkey_t dest, + const void *data, size_t size) +{ + assert(session != NULL); + char cmd[SAM_PKCMD_LEN]; + + if (size < 1 || size > SAM_RAW_PAYLOAD_MAX) { +#ifdef NO_Z_FORMAT + SAMLOG("Invalid data send size (%u bytes)", size); +#else + SAMLOG("Invalid data send size (%zu bytes)", size); +#endif + return SAM_TOO_BIG; + } +#ifdef NO_Z_FORMAT + snprintf(cmd, sizeof cmd, "RAW SEND DESTINATION=%s SIZE=%u\n", + dest, size); +#else + snprintf(cmd, sizeof cmd, "RAW SEND DESTINATION=%s SIZE=%zu\n", + dest, size); +#endif + sam_write(session, cmd, strlen(cmd)); + sam_write(session, data, size); + + return SAM_OK; +} + /* * Reads and callbacks everything in the SAM network buffer until it is clear *