summaryrefslogtreecommitdiff
path: root/code/core
diff options
context:
space:
mode:
authorUros Majstorovic <majstor@majstor.org>2017-07-23 10:17:38 +0200
committerUros Majstorovic <majstor@majstor.org>2017-07-23 10:17:38 +0200
commit804f291bd719c868778e2c624245113c219b3a36 (patch)
treef46bde25e9db331d06189dd8ed55233a6bbfb01a /code/core
parentd580fc0e00bf4b7acd3f9ee3345fad32223b40db (diff)
pre postira
Diffstat (limited to 'code/core')
-rw-r--r--code/core/core.c64
-rw-r--r--code/core/core.h16
-rw-r--r--code/core/rbuf.h3
-rw-r--r--code/core/rbuf_recv.c1
-rw-r--r--code/core/rbuf_send.c64
5 files changed, 80 insertions, 68 deletions
diff --git a/code/core/core.c b/code/core/core.c
index 812e48c..ae654c9 100644
--- a/code/core/core.c
+++ b/code/core/core.c
@@ -483,9 +483,10 @@ void ecp_conn_unregister(ECPConnection *conn) {
static ssize_t _conn_send_kget(ECPConnection *conn, ECPTimerItem *ti) {
unsigned char payload[ECP_SIZE_PLD(0)];
+ ecp_seq_t seq;
ecp_pld_set_type(payload, ECP_MTYPE_KGET);
- return ecp_pld_send_wkey(conn, ECP_ECDH_IDX_PERMA, ECP_ECDH_IDX_INV, payload, sizeof(payload));
+ return ecp_pld_send_wkey(conn, &seq, ECP_ECDH_IDX_PERMA, ECP_ECDH_IDX_INV, payload, sizeof(payload));
}
int ecp_conn_init(ECPConnection *conn, ECPNode *node) {
@@ -833,7 +834,7 @@ int ecp_conn_dhkey_get_curr(ECPConnection *conn, unsigned char *idx, unsigned ch
return ECP_OK;
}
-ssize_t ecp_pack(ECPContext *ctx, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, unsigned char *seq, unsigned char *payload, size_t payload_size) {
+ssize_t ecp_pack(ECPContext *ctx, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, unsigned char *payload, size_t payload_size) {
ssize_t rv;
if (payload == NULL) return ECP_ERR;
@@ -848,7 +849,10 @@ ssize_t ecp_pack(ECPContext *ctx, unsigned char *packet, size_t pkt_size, unsign
ctx->cr.dh_pub_to_buf(packet+ECP_SIZE_PROTO+1, public);
memcpy(packet+ECP_SIZE_PROTO+1+ECP_ECDH_SIZE_KEY, nonce, ECP_AEAD_SIZE_NONCE);
- memcpy(payload, seq, ECP_SIZE_SEQ);
+ payload[0] = (seq & 0xFF000000) >> 24;
+ payload[1] = (seq & 0x00FF0000) >> 16;
+ payload[2] = (seq & 0x0000FF00) >> 8;
+ payload[3] = (seq & 0x000000FF);
rv = ctx->cr.aead_enc(packet+ECP_SIZE_PKT_HDR, pkt_size-ECP_SIZE_PKT_HDR, payload, payload_size, shsec, nonce);
if (rv < 0) return ECP_ERR_ENCRYPT;
@@ -857,11 +861,10 @@ ssize_t ecp_pack(ECPContext *ctx, unsigned char *packet, size_t pkt_size, unsign
return rv+ECP_SIZE_PKT_HDR;
}
-ssize_t ecp_conn_pack(ECPConnection *conn, ECPNetAddr *addr, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size) {
+ssize_t ecp_conn_pack(ECPConnection *conn, ECPNetAddr *addr, ecp_seq_t *seq, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size) {
ecp_aead_key_t shsec;
ecp_dh_public_t public;
unsigned char nonce[ECP_AEAD_SIZE_NONCE];
- unsigned char seq[ECP_SIZE_SEQ];
int rv = ECP_OK;
#ifdef ECP_WITH_PTHREAD
@@ -895,11 +898,10 @@ ssize_t ecp_conn_pack(ECPConnection *conn, ECPNetAddr *addr, unsigned char *pack
}
if (!rv) {
- conn->seq_out++;
- seq[0] = (conn->seq_out & 0xFF000000) >> 24;
- seq[1] = (conn->seq_out & 0x00FF0000) >> 16;
- seq[2] = (conn->seq_out & 0x0000FF00) >> 8;
- seq[3] = (conn->seq_out & 0x000000FF);
+ if (seq) {
+ conn->seq_out++;
+ *seq = conn->seq_out;
+ }
if (addr) *addr = conn->node.addr;
}
@@ -909,7 +911,7 @@ ssize_t ecp_conn_pack(ECPConnection *conn, ECPNetAddr *addr, unsigned char *pack
if (rv) return rv;
- ssize_t _rv = ecp_pack(conn->sock->ctx, packet, pkt_size, s_idx, c_idx, &public, &shsec, nonce, seq, payload, payload_size);
+ ssize_t _rv = ecp_pack(conn->sock->ctx, packet, pkt_size, s_idx, c_idx, &public, &shsec, nonce, seq ? *seq : 0, payload, payload_size);
if (_rv < 0) return _rv;
#ifdef ECP_WITH_PTHREAD
@@ -923,17 +925,17 @@ ssize_t ecp_conn_pack(ECPConnection *conn, ECPNetAddr *addr, unsigned char *pack
return _rv;
}
-ssize_t ecp_proxy_pack(ECPConnection *conn, ECPNetAddr *addr, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size) {
+ssize_t ecp_proxy_pack(ECPConnection *conn, ECPNetAddr *addr, ecp_seq_t *seq, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size) {
ECPContext *ctx = conn->sock->ctx;
if (conn->proxy && ctx->pr.init) {
- return ctx->pr.pack(conn, addr, packet, pkt_size, s_idx, c_idx, payload, payload_size);
+ return ctx->pr.pack(conn, addr, seq, packet, pkt_size, s_idx, c_idx, payload, payload_size);
} else {
- return ecp_conn_pack(conn, addr, packet, pkt_size, s_idx, c_idx, payload, payload_size);
+ return ecp_conn_pack(conn, addr, seq, packet, pkt_size, s_idx, c_idx, payload, payload_size);
}
}
-ssize_t ecp_proxy_pack_raw(ECPSocket *sock, ECPConnection *proxy, ECPNetAddr *addr, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, unsigned char *seq, unsigned char *payload, size_t payload_size) {
+ssize_t ecp_proxy_pack_raw(ECPSocket *sock, ECPConnection *proxy, ECPNetAddr *addr, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, unsigned char *payload, size_t payload_size) {
ECPContext *ctx = sock->ctx;
if (proxy && ctx->pr.init) {
@@ -1038,7 +1040,7 @@ ssize_t ecp_pkt_handle(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *proxy,
rv = ecp_sock_dhkey_get_curr(sock, buf, buf+1);
if (!rv) {
- ssize_t _rv = ecp_pld_send_raw(sock, proxy, addr, s_idx, c_idx, &public, &shsec, nonce, payload, payload_, sizeof(payload_));
+ ssize_t _rv = ecp_pld_send_raw(sock, proxy, addr, s_idx, c_idx, &public, &shsec, nonce, p_seq, payload_, sizeof(payload_));
if (_rv < 0) rv = _rv;
}
return ECP_MIN_PKT;
@@ -1080,6 +1082,9 @@ ssize_t ecp_pkt_handle(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *proxy,
if (conn == NULL) return ECP_ERR;
+ proc_size = 0;
+ cnt_size = pld_size-ECP_SIZE_PLD_HDR;
+
#ifdef ECP_WITH_PTHREAD
pthread_mutex_lock(&conn->mutex);
#endif
@@ -1089,17 +1094,10 @@ ssize_t ecp_pkt_handle(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *proxy,
pthread_mutex_unlock(&conn->mutex);
#endif
- cnt_size = pld_size-ECP_SIZE_PLD_HDR;
-
#ifdef ECP_WITH_RBUF
- if (conn->rbuf.recv) {
- proc_size = ecp_msg_handle(conn, p_seq, payload+pld_size-cnt_size, cnt_size);
- } else {
- proc_size = ecp_rbuf_recv_store(conn, p_seq, payload+pld_size-cnt_size, cnt_size);
- }
-#else
- proc_size = ecp_msg_handle(conn, p_seq, payload+pld_size-cnt_size, cnt_size);
+ if (conn->rbuf.recv && conn->rbuf.recv->open) proc_size = ecp_rbuf_recv_store(conn, p_seq, payload+pld_size-cnt_size, cnt_size);
#endif
+ if (proc_size == 0) proc_size = ecp_msg_handle(conn, p_seq, payload+pld_size-cnt_size, cnt_size);
if (proc_size < 0) rv = ECP_ERR_HANDLE;
if (!rv) cnt_size -= proc_size;
@@ -1202,23 +1200,29 @@ unsigned char ecp_pld_get_type(unsigned char *payload) {
}
ssize_t ecp_pld_send(ECPConnection *conn, unsigned char *payload, size_t payload_size) {
- return ecp_pld_send_wkey(conn, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, payload, payload_size);
+ ecp_seq_t seq;
+ return ecp_pld_send_wkey(conn, &seq, ECP_ECDH_IDX_INV, ECP_ECDH_IDX_INV, payload, payload_size);
}
-ssize_t ecp_pld_send_wkey(ECPConnection *conn, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size) {
+ssize_t ecp_pld_send_wkey(ECPConnection *conn, ecp_seq_t *seq, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size) {
unsigned char packet[ECP_MAX_PKT];
ECPSocket *sock = conn->sock;
ECPNetAddr addr;
ssize_t rv;
- rv = ecp_proxy_pack(conn, &addr, packet, ECP_MAX_PKT, s_idx, c_idx, payload, payload_size);
+ rv = ecp_proxy_pack(conn, &addr, seq, packet, ECP_MAX_PKT, s_idx, c_idx, payload, payload_size);
if (rv < 0) return rv;
- // XXX insert ecp_rbuf_send_store
+#ifdef ECP_WITH_RBUF
+ if (conn->rbuf.send && conn->rbuf.send->open && seq) {
+ ssize_t _rv = ecp_rbuf_send_store(conn, *seq, packet, rv);
+ if (_rv < 0) return _rv;
+ }
+#endif
return ecp_pkt_send(sock, &addr, packet, rv);
}
-ssize_t ecp_pld_send_raw(ECPSocket *sock, ECPConnection *proxy, ECPNetAddr *addr, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, unsigned char *seq, unsigned char *payload, size_t payload_size) {
+ssize_t ecp_pld_send_raw(ECPSocket *sock, ECPConnection *proxy, ECPNetAddr *addr, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, unsigned char *payload, size_t payload_size) {
unsigned char packet[ECP_MAX_PKT];
ECPNetAddr _addr;
ssize_t rv;
diff --git a/code/core/core.h b/code/core/core.h
index cb9bab6..46f0d70 100644
--- a/code/core/core.h
+++ b/code/core/core.h
@@ -155,8 +155,8 @@ typedef struct ECPTimeIface {
typedef struct ECPProxyIface {
int init;
- ssize_t (*pack) (struct ECPConnection *conn, ECPNetAddr *addr, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size);
- ssize_t (*pack_raw) (struct ECPConnection *proxy, ECPNetAddr *addr, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, unsigned char *seq, unsigned char *payload, size_t payload_size);
+ ssize_t (*pack) (struct ECPConnection *conn, ECPNetAddr *addr, ecp_seq_t *seq, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size);
+ ssize_t (*pack_raw) (struct ECPConnection *proxy, ECPNetAddr *addr, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, unsigned char *payload, size_t payload_size);
} ECPProxyIface;
typedef struct ECPDHKey {
@@ -301,10 +301,10 @@ int ecp_conn_dhkey_new(ECPConnection *conn);
int ecp_conn_dhkey_new_pub(ECPConnection *conn, unsigned char idx, unsigned char *public);
int ecp_conn_dhkey_get_curr(ECPConnection *conn, unsigned char *idx, unsigned char *public);
-ssize_t ecp_pack(ECPContext *ctx, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, unsigned char *seq, unsigned char *payload, size_t payload_size);
-ssize_t ecp_conn_pack(ECPConnection *conn, ECPNetAddr *addr, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size);
-ssize_t ecp_proxy_pack(ECPConnection *conn, ECPNetAddr *addr, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size);
-ssize_t ecp_proxy_pack_raw(ECPSocket *sock, ECPConnection *proxy, ECPNetAddr *addr, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, unsigned char *seq, unsigned char *payload, size_t payload_size);
+ssize_t ecp_pack(ECPContext *ctx, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, unsigned char *payload, size_t payload_size);
+ssize_t ecp_conn_pack(ECPConnection *conn, ECPNetAddr *addr, ecp_seq_t *seq, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size);
+ssize_t ecp_proxy_pack(ECPConnection *conn, ECPNetAddr *addr, ecp_seq_t *seq, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size);
+ssize_t ecp_proxy_pack_raw(ECPSocket *sock, ECPConnection *proxy, ECPNetAddr *addr, unsigned char *packet, size_t pkt_size, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, unsigned char *payload, size_t payload_size);
ssize_t ecp_pkt_handle(ECPSocket *sock, ECPNetAddr *addr, ECPConnection *proxy, unsigned char *packet, size_t pkt_size);
ssize_t ecp_pkt_send(ECPSocket *sock, ECPNetAddr *addr, unsigned char *packet, size_t pkt_size);
@@ -315,8 +315,8 @@ unsigned char *ecp_pld_get_buf(unsigned char *payload);
void ecp_pld_set_type(unsigned char *payload, unsigned char mtype);
unsigned char ecp_pld_get_type(unsigned char *payload);
ssize_t ecp_pld_send(ECPConnection *conn, unsigned char *payload, size_t payload_size);
-ssize_t ecp_pld_send_wkey(ECPConnection *conn, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size);
-ssize_t ecp_pld_send_raw(ECPSocket *sock, ECPConnection *proxy, ECPNetAddr *addr, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, unsigned char *seq, unsigned char *payload, size_t payload_size);
+ssize_t ecp_pld_send_wkey(ECPConnection *conn, ecp_seq_t *seq, unsigned char s_idx, unsigned char c_idx, unsigned char *payload, size_t payload_size);
+ssize_t ecp_pld_send_raw(ECPSocket *sock, ECPConnection *proxy, ECPNetAddr *addr, unsigned char s_idx, unsigned char c_idx, ecp_dh_public_t *public, ecp_aead_key_t *shsec, unsigned char *nonce, ecp_seq_t seq, unsigned char *payload, size_t payload_size);
ssize_t ecp_send(ECPConnection *conn, unsigned char *payload, size_t payload_size);
ssize_t ecp_receive(ECPConnection *conn, unsigned char mtype, unsigned char *msg, size_t msg_size, unsigned int timeout);
diff --git a/code/core/rbuf.h b/code/core/rbuf.h
index 3577211..4340707 100644
--- a/code/core/rbuf.h
+++ b/code/core/rbuf.h
@@ -24,6 +24,7 @@ typedef struct ECPRBMessage {
unsigned char msg[ECP_MAX_PKT];
ssize_t size;
unsigned char flags;
+ ECPNetAddr addr;
} ECPRBMessage;
typedef struct ECPRBuffer {
@@ -34,6 +35,7 @@ typedef struct ECPRBuffer {
} ECPRBuffer;
typedef struct ECPRBRecv {
+ unsigned char open;
unsigned char reliable;
unsigned short deliver_delay;
unsigned short hole_max;
@@ -48,6 +50,7 @@ typedef struct ECPRBRecv {
} ECPRBRecv;
typedef struct ECPRBSend {
+ unsigned char open;
unsigned char reliable;
ecp_win_t win_size;
ecp_win_t in_transit;
diff --git a/code/core/rbuf_recv.c b/code/core/rbuf_recv.c
index 9b96be2..6a46a00 100644
--- a/code/core/rbuf_recv.c
+++ b/code/core/rbuf_recv.c
@@ -79,6 +79,7 @@ int ecp_rbuf_recv_create(ECPRBRecv *buf, ECPRBMessage *msg, unsigned int msg_siz
ecp_rbuf_init(&buf->rbuf, msg, msg_size);
buf->ack_map = ECP_RBUF_ACK_FULL;
buf->ack_rate = ACK_RATE;
+
return ECP_OK;
}
diff --git a/code/core/rbuf_send.c b/code/core/rbuf_send.c
index 8f0cc38..7ae5aca 100644
--- a/code/core/rbuf_send.c
+++ b/code/core/rbuf_send.c
@@ -12,48 +12,44 @@ static ssize_t handle_ack(ECPConnection *conn, ecp_seq_t seq, unsigned char mtyp
ECPRBSend *buf = conn->rbuf.send;
ECPRBuffer *rbuf = &buf->rbuf;
+ idx = ecp_rbuf_msg_idx(rbuf, seq_ack);
+ if (idx < 0) return idx;
+
+ seq_ack++;
+ buf->in_transit -= seq_ack - rbuf->seq_start;
+
if (ack_map != ECP_RBUF_ACK_FULL) {
int i;
int nack = 0;
- ecp_win_t ack_cnt = 0;
+ ecp_win_t nack_cnt = 0;
- seq_ack -= ECP_RBUF_ACK_SIZE - 1;
-
- idx = ecp_rbuf_msg_idx(rbuf, seq_ack);
- if (idx < 0) return idx;
-
- if (buf->reliable) buf->in_transit -= seq_ack - rbuf->seq_start;
+ seq_ack -= ECP_RBUF_ACK_SIZE;
for (i=0; i<ECP_RBUF_ACK_SIZE; i++) {
- if (ack_map & ((ecp_ack_t)1 << (ECP_RBUF_ACK_SIZE - i - 1))) {
- ack_cnt++;
- } else if (buf->reliable) {
- // if resend packet (seq_ack + i)
- if (!nack) {
- nack = 1;
-
- rbuf->seq_start = seq_ack + i;
- rbuf->msg_start = ECP_RBUF_IDX_MASK(idx + i, rbuf->msg_size);
+ if ((ack_map & ((ecp_ack_t)1 << (ECP_RBUF_ACK_SIZE - i - 1))) == 0) {
+ nack_cnt++;
+ if (buf->reliable) {
+ idx = ecp_rbuf_msg_idx(rbuf, seq_ack + i);
+ // resend packet
+ // ecp_pkt_send(conn->sock, &conn->node.addr, packet, rv);
+ if (!nack) {
+ nack = 1;
+
+ rbuf->seq_start = seq_ack + i;
+ rbuf->msg_start = idx;
+ }
}
}
}
- if (buf->reliable) {
- buf->in_transit -= ack_cnt;
- } else {
+ buf->in_transit += nack_cnt;
+ buf->nack_rate = (buf->nack_rate * 7 + ((ECP_RBUF_ACK_SIZE - nack_cnt) * ACK_RATE_UNIT) / ECP_RBUF_ACK_SIZE) / 8;
+ if (!buf->reliable) {
rbuf->seq_start = seq_ack + ECP_RBUF_ACK_SIZE;
- buf->nack_rate = (buf->nack_rate * 7 + ((ECP_RBUF_ACK_SIZE - ack_cnt) * ACK_RATE_UNIT) / ECP_RBUF_ACK_SIZE) / 8;
}
} else {
- seq_ack++;
-
- idx = ecp_rbuf_msg_idx(rbuf, seq_ack);
- if (idx < 0) return idx;
-
rbuf->seq_start = seq_ack;
+ buf->nack_rate = (buf->nack_rate * 7) / 8;
if (buf->reliable) {
- buf->in_transit -= seq_ack - rbuf->seq_start;
- rbuf->msg_start = idx;
- } else {
- buf->nack_rate = (buf->nack_rate * 7) / 8;
+ rbuf->msg_start = ECP_RBUF_IDX_MASK(idx + 1, rbuf->msg_size);
}
}
return size;
@@ -63,11 +59,19 @@ int ecp_rbuf_send_create(ECPRBSend *buf, ECPRBMessage *msg, unsigned int msg_siz
memset(buf, 0, sizeof(ECPRBRecv));
memset(msg, 0, sizeof(ECPRBMessage) * msg_size);
ecp_rbuf_init(&buf->rbuf, msg, msg_size);
+
+ return ECP_OK;
+}
+
+int ecp_rbuf_send_start(ECPRBSend *buf, ecp_seq_t seq) {
+ buf->rbuf.seq_start = seq + 1;
+
return ECP_OK;
}
ssize_t ecp_rbuf_send_store(ECPConnection *conn, ecp_seq_t seq, unsigned char *msg, size_t msg_size) {
ECPRBSend *buf = conn->rbuf.send;
- if (buf->reliable) buf->in_transit++;
+
+ buf->in_transit++;
return ecp_rbuf_msg_store(&buf->rbuf, seq, msg, msg_size, 0, 0);
} \ No newline at end of file