Class: Socket::Option

Inherits:
Object
  • Object
show all
Defined in:
option.c,
option.c

Overview

Socket::Option represents a socket option used by BasicSocket#getsockopt and BasicSocket#setsockopt. A socket option contains the socket #family, protocol #level, option name #optname and option value #data.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#Socket::Option.new(family, level, optname, data) ⇒ Object

Returns a new Socket::Option object.

sockopt = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i"))
p sockopt #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>


92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'option.c', line 92

static VALUE
sockopt_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE data)
{
    int family = rsock_family_arg(vfamily);
    int level = rsock_level_arg(family, vlevel);
    int optname = rsock_optname_arg(family, level, voptname);
    StringValue(data);
    rb_ivar_set(self, rb_intern("family"), INT2NUM(family));
    rb_ivar_set(self, rb_intern("level"), INT2NUM(level));
    rb_ivar_set(self, rb_intern("optname"), INT2NUM(optname));
    rb_ivar_set(self, rb_intern("data"), data);
    return self;
}

Class Method Details

.Socket::Option.bool(family, level, optname, bool) ⇒ Object

Creates a new Socket::Option object which contains boolean as data. Actually 0 or 1 as int is used.

require 'socket'

p Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true)
#=> #<Socket::Option: INET SOCKET KEEPALIVE 1>

p Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, false)
#=> #<Socket::Option: AF_INET SOCKET KEEPALIVE 0>


284
285
286
287
288
289
290
291
292
# File 'option.c', line 284

static VALUE
sockopt_s_bool(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vbool)
{
    int family = rsock_family_arg(vfamily);
    int level = rsock_level_arg(family, vlevel);
    int optname = rsock_optname_arg(family, level, voptname);
    int i = RTEST(vbool) ? 1 : 0;
    return rsock_sockopt_new(family, level, optname, pack_var(i));
}

.Socket::Option.byte(family, level, optname, integer) ⇒ Object

Creates a new Socket::Option object which contains a byte as data.

p Socket::Option.byte(:INET, :SOCKET, :KEEPALIVE, 1)
#=> #<Socket::Option: INET SOCKET KEEPALIVE 1>


199
200
201
202
203
204
205
206
# File 'option.c', line 199

static VALUE
sockopt_s_byte(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vint)
{
    int family = rsock_family_arg(vfamily);
    int level = rsock_level_arg(family, vlevel);
    int optname = rsock_optname_arg(family, level, voptname);
    return rsock_sockopt_new(family, level, optname, sockopt_pack_byte(vint));
}

.Socket::Option.int(family, level, optname, integer) ⇒ Object

Creates a new Socket::Option object which contains an int as data.

The size and endian is dependent on the platform.

p Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
#=> #<Socket::Option: INET SOCKET KEEPALIVE 1>


237
238
239
240
241
242
243
244
# File 'option.c', line 237

static VALUE
sockopt_s_int(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vint)
{
    int family = rsock_family_arg(vfamily);
    int level = rsock_level_arg(family, vlevel);
    int optname = rsock_optname_arg(family, level, voptname);
    return rsock_sockopt_new(family, level, optname, sockopt_pack_int(vint));
}

.Socket::Option.ipv4_multicast_loop(integer) ⇒ Object

Creates a new Socket::Option object for IP_MULTICAST_LOOP.

The size is dependent on the platform.

sockopt = Socket::Option.int(:INET, :IPPROTO_IP, :IP_MULTICAST_LOOP, 1)
p sockopt.int => 1

p Socket::Option.ipv4_multicast_loop(10)
#=> #<Socket::Option: INET IP MULTICAST_LOOP 10>


393
394
395
396
397
398
399
400
401
402
403
# File 'option.c', line 393

static VALUE
sockopt_s_ipv4_multicast_loop(VALUE klass, VALUE value)
{

#if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP)
    VALUE o = XCAT(sockopt_pack_,TYPE_IP_MULTICAST_LOOP)(value);
    return rsock_sockopt_new(AF_INET, IPPROTO_IP, IP_MULTICAST_LOOP, o);
#else
# error IPPROTO_IP or IP_MULTICAST_LOOP is not implemented
#endif
}

.Socket::Option.ipv4_multicast_ttl(integer) ⇒ Object

Creates a new Socket::Option object for IP_MULTICAST_TTL.

The size is dependent on the platform.

p Socket::Option.ipv4_multicast_ttl(10)
#=> #<Socket::Option: INET IP MULTICAST_TTL 10>


445
446
447
448
449
450
451
452
453
454
# File 'option.c', line 445

static VALUE
sockopt_s_ipv4_multicast_ttl(VALUE klass, VALUE value)
{
#if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
    VALUE o = XCAT(sockopt_pack_,TYPE_IP_MULTICAST_TTL)(value);
    return rsock_sockopt_new(AF_INET, IPPROTO_IP, IP_MULTICAST_TTL, o);
#else
# error IPPROTO_IP or IP_MULTICAST_TTL is not implemented
#endif
}

.Socket::Option.linger(onoff, secs) ⇒ Object

Creates a new Socket::Option object for SOL_SOCKET/SO_LINGER.

onoff should be an integer or a boolean.

secs should be the number of seconds.

p Socket::Option.linger(true, 10)
#=> #<Socket::Option: UNSPEC SOCKET LINGER on 10sec>


333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'option.c', line 333

static VALUE
sockopt_s_linger(VALUE klass, VALUE vonoff, VALUE vsecs)
{
    VALUE tmp;
    struct linger l;
    memset(&l, 0, sizeof(l));
    if (!NIL_P(tmp = rb_check_to_integer(vonoff, "to_int")))
        l.l_onoff = NUM2INT(tmp);
    else
        l.l_onoff = RTEST(vonoff) ? 1 : 0;
    l.l_linger = NUM2INT(vsecs);
    return rsock_sockopt_new(AF_UNSPEC, SOL_SOCKET, SO_LINGER, pack_var(l));
}

Instance Method Details

#boolBoolean

Returns the data in sockopt as an boolean value.

sockopt = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
p sockopt.bool => true

Returns:

  • (Boolean)


303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'option.c', line 303

static VALUE
sockopt_bool(VALUE self)
{
    int i;
    long len;
    VALUE data = sockopt_data(self);
    StringValue(data);
    len = RSTRING_LEN(data);
    if (len == 1) {
	return *RSTRING_PTR(data) == 0 ? Qfalse : Qtrue;
    }
    check_size(len, sizeof(int));
    memcpy((char*)&i, RSTRING_PTR(data), len);
    return i == 0 ? Qfalse : Qtrue;
}

#byteInteger

Returns the data in sockopt as an byte.

sockopt = Socket::Option.byte(:INET, :SOCKET, :KEEPALIVE, 1)
p sockopt.byte => 1

Returns:

  • (Integer)


217
218
219
220
221
222
223
224
# File 'option.c', line 217

static VALUE
sockopt_byte(VALUE self)
{
    VALUE data = sockopt_data(self);
    StringValue(data);
    check_size(RSTRING_LEN(data), sizeof(char));
    return CHR2FIX(*RSTRING_PTR(data));
}

#dataString #to_sString

returns the socket option data as a string.

p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).data
#=> "\x01\x00\x00\x00"

Overloads:

  • #dataString

    Returns:

    • (String)
  • #to_sString

    Returns:

    • (String)


182
183
184
185
186
187
188
# File 'option.c', line 182

static VALUE
sockopt_data(VALUE self)
{
    VALUE v = rb_attr_get(self, rb_intern("data"));
    StringValue(v);
    return v;
}

#familyInteger

returns the socket family as an integer.

p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).family
#=> 10

Returns:

  • (Integer)


124
125
126
127
128
# File 'option.c', line 124

static VALUE
sockopt_family_m(VALUE self)
{
    return rb_attr_get(self, rb_intern("family"));
}

#inspectString

Returns a string which shows sockopt in human-readable form.

p Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i")).inspect
#=> "#<Socket::Option: INET SOCKET KEEPALIVE 1>"

Returns:

  • (String)


1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
# File 'option.c', line 1202

static VALUE
sockopt_inspect(VALUE self)
{
    int family = NUM2INT(sockopt_family_m(self));
    int level = NUM2INT(sockopt_level_m(self));
    int optname = NUM2INT(sockopt_optname_m(self));
    VALUE data = sockopt_data(self);
    VALUE v, ret;
    ID family_id, level_id, optname_id;
    int inspected;

    StringValue(data);

    ret = rb_sprintf("#<%s:", rb_obj_classname(self));

    family_id = rsock_intern_family_noprefix(family);
    if (family_id)
	rb_str_catf(ret, " %s", rb_id2name(family_id));
    else
        rb_str_catf(ret, " family:%d", family);

    if (level == SOL_SOCKET) {
        rb_str_cat2(ret, " SOCKET");

	optname_id = rsock_intern_so_optname(optname);
	if (optname_id)
	    rb_str_catf(ret, " %s", rb_id2name(optname_id));
	else
	    rb_str_catf(ret, " optname:%d", optname);
    }
#ifdef HAVE_SYS_UN_H
    else if (family == AF_UNIX) {
	rb_str_catf(ret, " level:%d", level);

	optname_id = rsock_intern_local_optname(optname);
	if (optname_id)
	    rb_str_catf(ret, " %s", rb_id2name(optname_id));
	else
	    rb_str_catf(ret, " optname:%d", optname);
    }
#endif
    else if (IS_IP_FAMILY(family)) {
	level_id = rsock_intern_iplevel(level);
	if (level_id)
	    rb_str_catf(ret, " %s", rb_id2name(level_id));
	else
	    rb_str_catf(ret, " level:%d", level);

	v = optname_to_sym(level, optname);
	if (SYMBOL_P(v))
	    rb_str_catf(ret, " %"PRIsVALUE, rb_sym2str(v));
	else
	    rb_str_catf(ret, " optname:%d", optname);
    }
    else {
        rb_str_catf(ret, " level:%d", level);
        rb_str_catf(ret, " optname:%d", optname);
    }

    inspected = 0;

    if (level == SOL_SOCKET)
        family = AF_UNSPEC;
    switch (family) {
      case AF_UNSPEC:
        switch (level) {
          case SOL_SOCKET:
            switch (optname) {
#            if defined(SO_DEBUG) /* POSIX */
              case SO_DEBUG: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(SO_ERROR) /* POSIX */
              case SO_ERROR: inspected = inspect_errno(level, optname, data, ret); break;
#            endif
#            if defined(SO_TYPE) /* POSIX */
              case SO_TYPE: inspected = inspect_socktype(level, optname, data, ret); break;
#            endif
#            if defined(SO_ACCEPTCONN) /* POSIX */
              case SO_ACCEPTCONN: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(SO_BROADCAST) /* POSIX */
              case SO_BROADCAST: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(SO_REUSEADDR) /* POSIX */
              case SO_REUSEADDR: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(SO_KEEPALIVE) /* POSIX */
              case SO_KEEPALIVE: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(SO_OOBINLINE) /* POSIX */
              case SO_OOBINLINE: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(SO_SNDBUF) /* POSIX */
              case SO_SNDBUF: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(SO_RCVBUF) /* POSIX */
              case SO_RCVBUF: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(SO_DONTROUTE) /* POSIX */
              case SO_DONTROUTE: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(SO_RCVLOWAT) /* POSIX */
              case SO_RCVLOWAT: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(SO_SNDLOWAT) /* POSIX */
              case SO_SNDLOWAT: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(SO_LINGER) /* POSIX */
              case SO_LINGER: inspected = inspect_linger(level, optname, data, ret); break;
#            endif
#            if defined(SO_RCVTIMEO) /* POSIX */
              case SO_RCVTIMEO: inspected = inspect_timeval_as_interval(level, optname, data, ret); break;
#            endif
#            if defined(SO_SNDTIMEO) /* POSIX */
              case SO_SNDTIMEO: inspected = inspect_timeval_as_interval(level, optname, data, ret); break;
#            endif
#            if defined(SO_PEERCRED) /* GNU/Linux, OpenBSD */
              case SO_PEERCRED: inspected = inspect_peercred(level, optname, data, ret); break;
#            endif
            }
            break;
        }
        break;

      case AF_INET:
#ifdef INET6
      case AF_INET6:
#endif
        switch (level) {
#        if defined(IPPROTO_IP)
          case IPPROTO_IP:
            switch (optname) {
#            if defined(IP_MULTICAST_IF) && defined(HAVE_TYPE_STRUCT_IP_MREQN) /* 4.4BSD, GNU/Linux */
              case IP_MULTICAST_IF: inspected = inspect_ipv4_multicast_if(level, optname, data, ret); break;
#            endif
#            if defined(IP_ADD_MEMBERSHIP) /* 4.4BSD, GNU/Linux */
              case IP_ADD_MEMBERSHIP: inspected = inspect_ipv4_add_drop_membership(level, optname, data, ret); break;
#            endif
#            if defined(IP_DROP_MEMBERSHIP) /* 4.4BSD, GNU/Linux */
              case IP_DROP_MEMBERSHIP: inspected = inspect_ipv4_add_drop_membership(level, optname, data, ret); break;
#            endif
#            if defined(IP_MULTICAST_LOOP) /* 4.4BSD, GNU/Linux */
              case IP_MULTICAST_LOOP: inspected = inspect_ipv4_multicast_loop(level, optname, data, ret); break;
#            endif
#            if defined(IP_MULTICAST_TTL) /* 4.4BSD, GNU/Linux */
              case IP_MULTICAST_TTL: inspected = inspect_ipv4_multicast_ttl(level, optname, data, ret); break;
#            endif
            }
            break;
#        endif

#        if defined(IPPROTO_IPV6)
          case IPPROTO_IPV6:
            switch (optname) {
#            if defined(IPV6_MULTICAST_HOPS) /* POSIX */
              case IPV6_MULTICAST_HOPS: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(IPV6_MULTICAST_IF) /* POSIX */
              case IPV6_MULTICAST_IF: inspected = inspect_ipv6_multicast_if(level, optname, data, ret); break;
#            endif
#            if defined(IPV6_MULTICAST_LOOP) /* POSIX */
              case IPV6_MULTICAST_LOOP: inspected = inspect_uint(level, optname, data, ret); break;
#            endif
#            if defined(IPV6_JOIN_GROUP) /* POSIX */
              case IPV6_JOIN_GROUP: inspected = inspect_ipv6_mreq(level, optname, data, ret); break;
#            endif
#            if defined(IPV6_LEAVE_GROUP) /* POSIX */
              case IPV6_LEAVE_GROUP: inspected = inspect_ipv6_mreq(level, optname, data, ret); break;
#            endif
#            if defined(IPV6_UNICAST_HOPS) /* POSIX */
              case IPV6_UNICAST_HOPS: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(IPV6_V6ONLY) /* POSIX */
              case IPV6_V6ONLY: inspected = inspect_int(level, optname, data, ret); break;
#            endif
            }
            break;
#        endif

#        if defined(IPPROTO_TCP)
          case IPPROTO_TCP:
            switch (optname) {
#            if defined(TCP_NODELAY) /* POSIX */
              case TCP_NODELAY: inspected = inspect_int(level, optname, data, ret); break;
#            endif
#            if defined(TCP_INFO) && defined(HAVE_TYPE_STRUCT_TCP_INFO) /* Linux, FreeBSD */
              case TCP_INFO: inspected = inspect_tcp_info(level, optname, data, ret); break;
#            endif
            }
            break;
#        endif
        }
        break;

#ifdef HAVE_SYS_UN_H
      case AF_UNIX:
        switch (level) {
          case 0:
            switch (optname) {
#            if defined(LOCAL_PEERCRED)
              case LOCAL_PEERCRED: inspected = inspect_local_peercred(level, optname, data, ret); break;
#            endif
            }
            break;
        }
        break;
#endif
    }

    if (!inspected) {
        rb_str_cat2(ret, " ");
        rb_str_append(ret, rb_str_dump(data));
    }

    rb_str_cat2(ret, ">");

    return ret;
}

#intInteger

Returns the data in sockopt as an int.

The size and endian is dependent on the platform.

sockopt = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
p sockopt.int => 1

Returns:

  • (Integer)


257
258
259
260
261
262
263
264
265
266
# File 'option.c', line 257

static VALUE
sockopt_int(VALUE self)
{
    int i;
    VALUE data = sockopt_data(self);
    StringValue(data);
    check_size(RSTRING_LEN(data), sizeof(int));
    memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
    return INT2NUM(i);
}

#ipv4_multicast_loopInteger

Returns the ipv4_multicast_loop data in sockopt as an integer.

sockopt = Socket::Option.ipv4_multicast_loop(10)
p sockopt.ipv4_multicast_loop => 10

Returns:

  • (Integer)


414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
# File 'option.c', line 414

static VALUE
sockopt_ipv4_multicast_loop(VALUE self)
{
    int family = NUM2INT(sockopt_family_m(self));
    int level = sockopt_level(self);
    int optname = sockopt_optname(self);

#if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP)
    if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_LOOP) {
	return XCAT(sockopt_,TYPE_IP_MULTICAST_LOOP)(self);
    }
#endif
    rb_raise(rb_eTypeError, "ipv4_multicast_loop socket option expected");
    UNREACHABLE_RETURN(Qnil);
}

#ipv4_multicast_ttlInteger

Returns the ipv4_multicast_ttl data in sockopt as an integer.

sockopt = Socket::Option.ipv4_multicast_ttl(10)
p sockopt.ipv4_multicast_ttl => 10

Returns:

  • (Integer)


465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
# File 'option.c', line 465

static VALUE
sockopt_ipv4_multicast_ttl(VALUE self)
{
    int family = NUM2INT(sockopt_family_m(self));
    int level = sockopt_level(self);
    int optname = sockopt_optname(self);

#if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
    if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_TTL) {
	return XCAT(sockopt_,TYPE_IP_MULTICAST_TTL)(self);
    }
#endif
    rb_raise(rb_eTypeError, "ipv4_multicast_ttl socket option expected");
    UNREACHABLE_RETURN(Qnil);
}

#levelInteger

returns the socket level as an integer.

p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).level
#=> 41

Returns:

  • (Integer)


145
146
147
148
149
# File 'option.c', line 145

static VALUE
sockopt_level_m(VALUE self)
{
    return INT2NUM(sockopt_level(self));
}

#lingerArray

Returns the linger data in sockopt as a pair of boolean and integer.

sockopt = Socket::Option.linger(true, 10)
p sockopt.linger => [true, 10]

Returns:

  • (Array)


356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
# File 'option.c', line 356

static VALUE
sockopt_linger(VALUE self)
{
    int level = sockopt_level(self);
    int optname = sockopt_optname(self);
    VALUE data = sockopt_data(self);
    struct linger l;
    VALUE vonoff, vsecs;

    if (level != SOL_SOCKET || optname != SO_LINGER)
        rb_raise(rb_eTypeError, "linger socket option expected");
    check_size(RSTRING_LEN(data), sizeof(struct linger));
    memcpy((char*)&l, RSTRING_PTR(data), sizeof(struct linger));
    switch (l.l_onoff) {
      case 0: vonoff = Qfalse; break;
      case 1: vonoff = Qtrue; break;
      default: vonoff = INT2NUM(l.l_onoff); break;
    }
    vsecs = INT2NUM(l.l_linger);
    return rb_assoc_new(vonoff, vsecs);
}

#optnameInteger

returns the socket option name as an integer.

p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).optname
#=> 2

Returns:

  • (Integer)


166
167
168
169
170
# File 'option.c', line 166

static VALUE
sockopt_optname_m(VALUE self)
{
    return INT2NUM(sockopt_optname(self));
}

#dataString #to_sString

returns the socket option data as a string.

p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).data
#=> "\x01\x00\x00\x00"

Overloads:

  • #dataString

    Returns:

    • (String)
  • #to_sString

    Returns:

    • (String)


182
183
184
185
186
187
188
# File 'option.c', line 182

static VALUE
sockopt_data(VALUE self)
{
    VALUE v = rb_attr_get(self, rb_intern("data"));
    StringValue(v);
    return v;
}

#unpack(template) ⇒ Array

Calls String#unpack on sockopt.data.

sockopt = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i"))
p sockopt.unpack("i")      #=> [1]
p sockopt.data.unpack("i") #=> [1]

Returns:

  • (Array)


1431
1432
1433
1434
1435
# File 'option.c', line 1431

static VALUE
sockopt_unpack(VALUE self, VALUE template)
{
    return rb_funcall(sockopt_data(self), rb_intern("unpack"), 1, template);
}