kcp 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bf16edd731053438f070b9bd3c31917fc51a6c0c33b38f650fbc81b5fc2f8db
4
- data.tar.gz: 7b04f35a6eca243cde48a7e8c7b1fa1818a93c50a5a9fb39df1f39ed51299f3c
3
+ metadata.gz: c7802d290ec502e834ab5f7eb1e9b4c7a4f664b677ecae6c6f001fce6be4cd3c
4
+ data.tar.gz: 58fc1060c2be20897078deb312bfd4e671a5d5dd72b9656205ee2ccf8cc6fa31
5
5
  SHA512:
6
- metadata.gz: 16e4a8fafb2265f223b54fd3ad7d89b9d15ac4fbbc33793606164e6ec1b04f478f5db203b1b703a244067abfe380422d35c0d7ece1ff04d4c269f44be47e6880
7
- data.tar.gz: fae9a45f110c3e0cbc9ccd4f364bcf71595c4e626bfc00921de7915343030d2ab830759a8d0871b3e1a6e429103d3f0755e679cdcd21cd1e7d7ab124eae3138c
6
+ metadata.gz: f01a77107b1821d1c32818c403982799e5a97b0dd214d6f9b8cb7e6419f1eb597849d31456f76abecadb75317d2a1a29bd85f3ea8694d88dcf57e2c6699d12d7
7
+ data.tar.gz: 2261acc0d59efcb3b94267a0b523e24fa9b036aa5ba7e18f52a2a857194051a94c1a2004d4ba1a993b7141e76e7ca9bfcae828ee7098c91aaaba66e2382b7edc
data/ext/kcp/kcp_native.c CHANGED
@@ -8,25 +8,36 @@
8
8
  #include <stdlib.h>
9
9
  #include <string.h>
10
10
 
11
+ typedef struct {
12
+ char *data;
13
+ int len;
14
+ } kcp_pkt;
15
+
11
16
  typedef struct {
12
17
  ikcpcb *kcp;
13
- char *out;
14
- int outlen;
15
- int outcap;
18
+ kcp_pkt *pkts;
19
+ int count;
20
+ int cap;
16
21
  } kcp_ctx;
17
22
 
18
- /* Max bytes returned per output() call -- safely under the 64KB UDP datagram
19
- limit, so a burst of KCP packets never overflows a single sendto(). */
20
- #define KCP_MAX_BLOB 60000
21
-
23
+ /* shim_output 每个 KCP 报文(≤ mtu)单独入队,output() 一次只取一个包,
24
+ 避免把多个 KCP 报文拼成一个大 blob,导致上层封成单个超大 UDP 数据报被
25
+ IP 分片(分片常被 NAT/防火墙丢弃,造成远端云主机连接异常)。 */
22
26
  static int shim_output(const char *buf, int len, ikcpcb *kcp, void *user) {
23
27
  kcp_ctx *ctx = (kcp_ctx *)user;
24
- if (ctx->outlen + len > ctx->outcap) {
25
- ctx->outcap = (ctx->outlen + len) * 2 + 256;
26
- ctx->out = (char *)realloc(ctx->out, ctx->outcap);
28
+ if (ctx->count >= ctx->cap) {
29
+ int newcap = ctx->cap ? ctx->cap * 2 : 32;
30
+ kcp_pkt *npkts = (kcp_pkt *)realloc(ctx->pkts, newcap * sizeof(kcp_pkt));
31
+ if (!npkts) return -1;
32
+ ctx->pkts = npkts;
33
+ ctx->cap = newcap;
27
34
  }
28
- memcpy(ctx->out + ctx->outlen, buf, len);
29
- ctx->outlen += len;
35
+ kcp_pkt *p = &ctx->pkts[ctx->count];
36
+ p->data = (char *)malloc(len);
37
+ if (!p->data) return -1;
38
+ memcpy(p->data, buf, len);
39
+ p->len = len;
40
+ ctx->count++;
30
41
  return 0;
31
42
  }
32
43
 
@@ -34,7 +45,8 @@ static void ctx_free(void *ptr) {
34
45
  kcp_ctx *ctx = (kcp_ctx *)ptr;
35
46
  if (ctx) {
36
47
  if (ctx->kcp) ikcp_release(ctx->kcp);
37
- free(ctx->out);
48
+ for (int i = 0; i < ctx->count; i++) free(ctx->pkts[i].data);
49
+ free(ctx->pkts);
38
50
  free(ctx);
39
51
  }
40
52
  }
@@ -108,17 +120,23 @@ static VALUE m_kcp_flush(VALUE mod, VALUE self) {
108
120
 
109
121
  static VALUE m_kcp_output(VALUE mod, VALUE self) {
110
122
  kcp_ctx *ctx = get_ctx(self);
111
- if (ctx->outlen <= 0) return Qnil;
112
- /* 一次最多返回 60KB 拼接好的包,避免单个 UDP 数据报超过 64KB(EMSGSIZE) */
113
- int n = ctx->outlen < KCP_MAX_BLOB ? ctx->outlen : KCP_MAX_BLOB;
114
- VALUE buf = rb_str_new(ctx->out, n);
115
- if (n < ctx->outlen) {
116
- memmove(ctx->out, ctx->out + n, ctx->outlen - n);
123
+ if (ctx->count <= 0) return Qnil;
124
+ /* 一次只返回一个 KCP 报文(≤ mtu),避免上层拼成超长 UDP 数据报触发 IP 分片 */
125
+ kcp_pkt p = ctx->pkts[0];
126
+ VALUE buf = rb_str_new(p.data, p.len);
127
+ free(p.data);
128
+ ctx->count--;
129
+ if (ctx->count > 0) {
130
+ memmove(&ctx->pkts[0], &ctx->pkts[1], ctx->count * sizeof(kcp_pkt));
117
131
  }
118
- ctx->outlen -= n;
119
132
  return buf;
120
133
  }
121
134
 
135
+ static VALUE m_kcp_setmtu(VALUE mod, VALUE self, VALUE mtu) {
136
+ kcp_ctx *ctx = get_ctx(self);
137
+ return INT2NUM(ikcp_setmtu(ctx->kcp, NUM2INT(mtu)));
138
+ }
139
+
122
140
  static VALUE m_kcp_waitsnd(VALUE mod, VALUE self) {
123
141
  kcp_ctx *ctx = get_ctx(self);
124
142
  return INT2NUM(ikcp_waitsnd(ctx->kcp));
@@ -133,5 +151,6 @@ void Init_kcp_native(void) {
133
151
  rb_define_singleton_method(m, "kcp_update", m_kcp_update, 2);
134
152
  rb_define_singleton_method(m, "kcp_flush", m_kcp_flush, 1);
135
153
  rb_define_singleton_method(m, "kcp_output", m_kcp_output, 1);
154
+ rb_define_singleton_method(m, "kcp_setmtu", m_kcp_setmtu, 2);
136
155
  rb_define_singleton_method(m, "kcp_waitsnd", m_kcp_waitsnd, 1);
137
156
  }
data/lib/kcp/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kcp
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  end
data/lib/kcp.rb CHANGED
@@ -57,6 +57,12 @@ module Kcp
57
57
  KcpNative.kcp_output(@ctx)
58
58
  end
59
59
 
60
+ # 设置 KCP 内部 MTU(默认 1400)。上层如 mnet 会额外加自己的 header + GCM tag,
61
+ # 需要把 MTU 调小,保证「KCP 包 + 外层封装」仍小于路径 MTU,避免 IP 分片。
62
+ def mtu=(mtu)
63
+ KcpNative.kcp_setmtu(@ctx, mtu)
64
+ end
65
+
60
66
  # 发送队列里待发送的包数(>0 表示窗口已满、有积压)。
61
67
  def waitsnd
62
68
  KcpNative.kcp_waitsnd(@ctx)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kcp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - kcp developers