summaryrefslogtreecommitdiffstats
path: root/PICA_client.c
diff options
context:
space:
mode:
authorAnton <anton@picapica>2025-06-05 02:01:59 +0400
committerAnton <anton@picapica>2025-06-05 02:01:59 +0400
commit1ba82ff025d3e1cc79687083acddabb7c24385d5 (patch)
treea5aa1f9204d88cbe6ebae09c048040ab210fbc7d /PICA_client.c
parent804a917df338d7e8403c729885d60195dfb65c5d (diff)
downloadpica-pica-1ba82ff025d3e1cc79687083acddabb7c24385d5.tar.gz
pica-pica-1ba82ff025d3e1cc79687083acddabb7c24385d5.zip
pica-client: call handling functions
Diffstat (limited to 'PICA_client.c')
-rw-r--r--PICA_client.c293
1 files changed, 291 insertions, 2 deletions
diff --git a/PICA_client.c b/PICA_client.c
index 4f814db..0737f94 100644
--- a/PICA_client.c
+++ b/PICA_client.c
@@ -76,7 +76,14 @@ static unsigned int procmsg_PICA_PROTO_DIRECTC2C_ADDRLIST(unsigned char*, unsign
static unsigned int procmsg_PICA_PROTO_DIRECTC2C_FAILED(unsigned char*, unsigned int, void*);
static unsigned int procmsg_PICA_PROTO_DIRECTC2C_SWITCH(unsigned char*, unsigned int, void*);
static unsigned int procmsg_MULTILOGIN(unsigned char*, unsigned int, void*);
-
+static unsigned int procmsg_CALLREQ(unsigned char*, unsigned int, void*);
+static unsigned int procmsg_CALLANS(unsigned char*, unsigned int, void*);
+static unsigned int procmsg_CALLREJ(unsigned char*, unsigned int, void*);
+static unsigned int procmsg_CALLFIN(unsigned char*, unsigned int, void*);
+static unsigned int procmsg_CALL_AUDIOPARAM(unsigned char*, unsigned int, void*);
+static unsigned int procmsg_CALL_VIDEOPARAM(unsigned char*, unsigned int, void*);
+static unsigned int procmsg_CALL_AUDIO_PACKET(unsigned char*, unsigned int, void*);
+static unsigned int procmsg_CALL_VIDEO_PACKET(unsigned char*, unsigned int, void*);
static struct PICA_proto_msg* c2n_writebuf_push(struct PICA_c2n *ci, unsigned int msgid, unsigned int size);
static struct PICA_proto_msg* c2c_writebuf_push(struct PICA_c2c *chn, unsigned int msgid, unsigned int size);
@@ -109,6 +116,14 @@ const struct PICA_msginfo c2c_messages[] =
{
{PICA_PROTO_MSGUTF8, PICA_MSG_VAR_SIZE, PICA_MSG_VARSIZE_INT16, procmsg_MSGUTF8},
{PICA_PROTO_MSGOK, PICA_MSG_FIXED_SIZE, PICA_PROTO_MSGOK_SIZE, procmsg_MSGOK},
+ {PICA_PROTO_CALLREQ, PICA_MSG_FIXED_SIZE, PICA_PROTO_CALLREQ_SIZE, procmsg_CALLREQ},
+ {PICA_PROTO_CALLANS, PICA_MSG_FIXED_SIZE, PICA_PROTO_CALLANS_SIZE, procmsg_CALLANS},
+ {PICA_PROTO_CALLREJ, PICA_MSG_FIXED_SIZE, PICA_PROTO_CALLREJ_SIZE, procmsg_CALLREJ},
+ {PICA_PROTO_CALLFIN, PICA_MSG_FIXED_SIZE, PICA_PROTO_CALLFIN_SIZE, procmsg_CALLFIN},
+ {PICA_PROTO_CALL_AUDIOPARAM, PICA_MSG_FIXED_SIZE, PICA_PROTO_CALL_AUDIOPARAM_SIZE, procmsg_CALL_AUDIOPARAM},
+ {PICA_PROTO_CALL_VIDEOPARAM, PICA_MSG_FIXED_SIZE, PICA_PROTO_CALL_VIDEOPARAM_SIZE, procmsg_CALL_VIDEOPARAM},
+ {PICA_PROTO_CALL_AUDIO_PACKET, PICA_MSG_VAR_SIZE, PICA_MSG_VARSIZE_INT16, procmsg_CALL_AUDIO_PACKET},
+ {PICA_PROTO_CALL_VIDEO_PACKET, PICA_MSG_VAR_SIZE, PICA_MSG_VARSIZE_INT16, procmsg_CALL_VIDEO_PACKET},
{PICA_PROTO_SENDFILEREQUEST, PICA_MSG_VAR_SIZE, PICA_MSG_VARSIZE_INT16, procmsg_SENDFILEREQUEST},
{PICA_PROTO_ACCEPTEDFILE, PICA_MSG_FIXED_SIZE, PICA_PROTO_ACCEPTEDFILE_SIZE, procmsg_ACCEPTEDFILE},
{PICA_PROTO_DENIEDFILE, PICA_MSG_FIXED_SIZE, PICA_PROTO_DENIEDFILE_SIZE, procmsg_DENIEDFILE},
@@ -1749,6 +1764,187 @@ multilogin_err1:
return 1;
}
+static unsigned int procmsg_CALLREQ(unsigned char*, unsigned int, void *p)
+{
+ struct PICA_c2c *chan = (struct PICA_c2c *)p;
+
+ if (chan->call_state != PICA_CALL_STATE_IDLE)
+ // busy, send reject
+ {
+ struct PICA_proto_msg *mp;
+ mp = c2c_writebuf_push( chan, PICA_PROTO_CALLREJ, PICA_PROTO_CALLREJ_SIZE);
+
+ if (mp)
+ {
+ RAND_pseudo_bytes( mp->tail, 2);
+ }
+ else
+ return 0;
+
+ return 1;
+ }
+
+ chan->call_state = PICA_CALL_STATE_INCOMINGCALL;
+ callbacks.incoming_call_cb(chan->peer_id);
+
+ return 1;
+}
+
+static unsigned int procmsg_CALLANS(unsigned char*, unsigned int, void *p)
+{
+ struct PICA_c2c *chan = (struct PICA_c2c *)p;
+
+ if (chan->call_state != PICA_CALL_STATE_CALLING)
+ {
+ fprintf(stderr, "unexpected CALLANS, we did not initiate a call");
+ return 0;
+ }
+
+ chan->call_state = PICA_CALL_STATE_ACTIVE;
+ callbacks.call_picked_up_cb(chan->peer_id);
+
+ return 1;
+}
+
+static unsigned int procmsg_CALLREJ(unsigned char*, unsigned int, void *p)
+{
+ struct PICA_c2c *chan = (struct PICA_c2c *)p;
+
+ if (chan->call_state != PICA_CALL_STATE_CALLING)
+ {
+ fprintf(stderr, "unexpected CALLREJ, we did not initiate a call");
+ return 0;
+ }
+
+ chan->call_state = PICA_CALL_STATE_IDLE;
+
+ callbacks.call_rejected_cb(chan->peer_id);
+
+ return 1;
+}
+
+static unsigned int procmsg_CALLFIN(unsigned char*, unsigned int, void *p)
+{
+ struct PICA_c2c *chan = (struct PICA_c2c *)p;
+
+ if (chan->call_state == PICA_CALL_STATE_IDLE)
+ {
+ fprintf(stderr, "unexpected CALLFIN, no call in progress");
+ return 0;
+ }
+
+ chan->call_state = PICA_CALL_STATE_IDLE;
+
+ callbacks.call_hangup_cb(chan->peer_id);
+
+ return 1;
+}
+
+static unsigned int procmsg_CALL_AUDIOPARAM(unsigned char* buf, unsigned int nb, void *p)
+{
+ struct PICA_c2c *chan = (struct PICA_c2c *)p;
+ char codecnamebuf[24];
+ uint16_t sample_rate;
+
+ if (chan->call_state != PICA_CALL_STATE_ACTIVE)
+ {
+ fprintf(stderr, "unexpected AUDIOPARAM, no call in progress");
+ return 0;
+ }
+
+ chan->call_audio_params_are_set = 1;
+
+ codecnamebuf[0] = '\0';
+ strncat(codecnamebuf, buf + 2, PICA_PROTO_CALL_CODECNAMESIZE);
+
+ sample_rate = *(uint16_t*)(buf + 2 + PICA_PROTO_CALL_CODECNAMESIZE);
+ callbacks.call_audio_params_cb(chan->peer_id, codecnamebuf, sample_rate);
+
+ return 1;
+}
+
+static unsigned int procmsg_CALL_VIDEOPARAM(unsigned char* buf, unsigned int nb, void *p)
+{
+ struct PICA_c2c *chan = (struct PICA_c2c *)p;
+ char codecnamebuf[24];
+ uint16_t width, height;
+
+ if (chan->call_state != PICA_CALL_STATE_ACTIVE)
+ {
+ fprintf(stderr, "unexpected VIDEOPARAM, no call in progress");
+ return 0;
+ }
+
+ chan->call_video_params_are_set = 1;
+
+ codecnamebuf[0] = '\0';
+ strncat(codecnamebuf, buf + 2, PICA_PROTO_CALL_CODECNAMESIZE);
+
+ width = *(uint16_t*)(buf + 2 + PICA_PROTO_CALL_CODECNAMESIZE);
+ height = *(uint16_t*)(buf + 2 + PICA_PROTO_CALL_CODECNAMESIZE + 2);
+ callbacks.call_video_params_cb(chan->peer_id, codecnamebuf, width, height);
+
+ return 1;
+}
+
+static unsigned int procmsg_CALL_AUDIO_PACKET(unsigned char *buf, unsigned int nb, void* p)
+{
+ struct PICA_c2c *chan = (struct PICA_c2c *)p;
+
+ if (chan->call_state != PICA_CALL_STATE_ACTIVE)
+ {
+ fprintf(stderr, "unexpected CALL_AUDIO_PACKET, no call in progress");
+ return 0;
+ }
+
+ if (!chan->call_audio_params_are_set)
+ {
+ fprintf(stderr, "no AUDIOPARAM was set, can't process AUDIO_PACKET");
+ return 0;
+ }
+
+
+ if (*(uint16_t*)(buf + 2) != (nb - 4))
+ {
+ return 0;
+ }
+
+ uint16_t pkt_size = *(uint16_t*)(buf + 2);
+
+ callbacks.call_audio_packet_cb(chan->peer_id, pkt_size, buf + 4);
+
+ return 1;
+}
+
+static unsigned int procmsg_CALL_VIDEO_PACKET(unsigned char *buf, unsigned int nb, void *p)
+{
+ struct PICA_c2c *chan = (struct PICA_c2c *)p;
+
+ if (chan->call_state != PICA_CALL_STATE_ACTIVE)
+ {
+ fprintf(stderr, "unexpected CALL_VIDEO_PACKET, no call in progress");
+ return 0;
+ }
+
+ if (!chan->call_video_params_are_set)
+ {
+ fprintf(stderr, "no VIDEOPARAM was set, can't process VIDEO_PACKET");
+ return 0;
+ }
+
+
+ if (*(uint16_t*)(buf + 2) != (nb - 4))
+ {
+ return 0;
+ }
+
+ uint16_t pkt_size = *(uint16_t*)(buf + 2);
+
+ callbacks.call_video_packet_cb(chan->peer_id, pkt_size, buf + 4);
+
+ return 1;
+}
+
static int c2n_optstage7_multilogin(struct PICA_c2n *c2n)
{
struct PICA_proto_msg *mp;
@@ -3420,6 +3616,8 @@ int PICA_start_call(struct PICA_c2c *chn)
return PICA_ERRNOMEM;
}
+ chn->call_state = PICA_CALL_STATE_CALLING;
+
return PICA_OK;
}
@@ -3439,6 +3637,8 @@ int PICA_pickup_call(struct PICA_c2c *chn)
return PICA_ERRNOMEM;
}
+ chn->call_state = PICA_CALL_STATE_ACTIVE;
+
return PICA_OK;
}
@@ -3458,6 +3658,8 @@ int PICA_reject_call(struct PICA_c2c *chn)
return PICA_ERRNOMEM;
}
+ chn->call_state = PICA_CALL_STATE_IDLE;
+
return PICA_OK;
}
@@ -3465,7 +3667,7 @@ int PICA_hangup_call(struct PICA_c2c *chn)
{
struct PICA_proto_msg *mp;
- if (chn->call_state != PICA_CALL_STATE_ACTIVE)
+ if (chn->call_state == PICA_CALL_STATE_IDLE)
return PICA_ERRCALLNOTINPROGRESS;
if ((mp = c2c_writebuf_push(chn, PICA_PROTO_CALLFIN, PICA_PROTO_CALLFIN_SIZE)))
@@ -3479,6 +3681,93 @@ int PICA_hangup_call(struct PICA_c2c *chn)
// release call resources??
// handle incoming last stream packets?
+ chn->call_state = PICA_CALL_STATE_IDLE;
+
+ return PICA_OK;
+}
+
+int PICA_set_call_audio_params(struct PICA_c2c *chn, const char *codec_name, uint16_t sample_rate)
+{
+ struct PICA_proto_msg *mp;
+
+ if (chn->call_state != PICA_CALL_STATE_ACTIVE)
+ return PICA_ERRCALLNOTINPROGRESS;
+
+ if ((mp = c2c_writebuf_push(chn, PICA_PROTO_CALL_AUDIOPARAM, PICA_PROTO_CALL_AUDIOPARAM_SIZE)))
+ {
+ strncpy(mp->tail, codec_name, PICA_PROTO_CALL_CODECNAMESIZE);
+ *((uint16_t*)(mp->tail + PICA_PROTO_CALL_CODECNAMESIZE)) = sample_rate;
+
+ }
+ else
+ {
+ return PICA_ERRNOMEM;
+ }
+
+ return PICA_OK;
+}
+
+int PICA_set_call_video_params(struct PICA_c2c *chn, const char *codec_name, uint16_t width, uint16_t height)
+{
+ struct PICA_proto_msg *mp;
+
+ if (chn->call_state != PICA_CALL_STATE_ACTIVE)
+ return PICA_ERRCALLNOTINPROGRESS;
+
+ if ((mp = c2c_writebuf_push(chn, PICA_PROTO_CALL_VIDEOPARAM, PICA_PROTO_CALL_VIDEOPARAM_SIZE)))
+ {
+ strncpy(mp->tail, codec_name, PICA_PROTO_CALL_CODECNAMESIZE);
+ *((uint16_t*)(mp->tail + PICA_PROTO_CALL_CODECNAMESIZE)) = width;
+ *((uint16_t*)(mp->tail + PICA_PROTO_CALL_CODECNAMESIZE + sizeof(width))) = height;
+
+ }
+ else
+ {
+ return PICA_ERRNOMEM;
+ }
+
+ return PICA_OK;
+}
+
+int PICA_send_audio_packet(struct PICA_c2c *chn, const char *buf, unsigned int len)
+{
+ struct PICA_proto_msg *mp;
+
+ if (chn->call_state != PICA_CALL_STATE_ACTIVE)
+ return PICA_ERRCALLNOTINPROGRESS;
+
+ if ((mp = c2c_writebuf_push(chn, PICA_PROTO_CALL_AUDIO_PACKET, len + 4)))
+ {
+ *((uint16_t*)mp->tail) = len;
+ memcpy(mp->tail + 2, buf, len);
+
+ }
+ else
+ {
+ return PICA_ERRNOMEM;
+ }
+
+ return PICA_OK;
+}
+
+int PICA_send_video_packet(struct PICA_c2c *chn, const char *buf, unsigned int len)
+{
+ struct PICA_proto_msg *mp;
+
+ if (chn->call_state != PICA_CALL_STATE_ACTIVE)
+ return PICA_ERRCALLNOTINPROGRESS;
+
+ if ((mp = c2c_writebuf_push(chn, PICA_PROTO_CALL_VIDEO_PACKET, len + 4)))
+ {
+ *((uint16_t*)mp->tail) = len;
+ memcpy(mp->tail + 2, buf, len);
+
+ }
+ else
+ {
+ return PICA_ERRNOMEM;
+ }
+
return PICA_OK;
}