From e21e1b840fc9cf8c4e468494c2d7d2267b7e88bb Mon Sep 17 00:00:00 2001 From: genxium Date: Tue, 24 Jan 2023 12:00:49 +0800 Subject: [PATCH] Drafted udp holepunching upsync pathway. --- battle_srv/protos/room_downsync_frame.pb.go | 101 ++++++- .../pbfiles/room_downsync_frame.proto | 7 + frontend/assets/scenes/offline_map.fire | 2 +- frontend/assets/scripts/OfflineMap.js | 9 +- ...om_downsync_frame_proto_bundle.forcemsg.js | 273 ++++++++++++++++++ .../runtime-src/Classes/udp_session.cpp | 44 ++- .../runtime-src/Classes/udp_session.hpp | 4 +- .../Classes/udp_session_bridge.cpp | 27 +- .../Classes/udp_session_bridge.hpp | 1 + frontend/settings/builder.json | 5 +- udp_server_prac/main.go | 31 ++ 11 files changed, 476 insertions(+), 28 deletions(-) create mode 100644 udp_server_prac/main.go diff --git a/battle_srv/protos/room_downsync_frame.pb.go b/battle_srv/protos/room_downsync_frame.pb.go index 72b2d25..ab8c56b 100644 --- a/battle_srv/protos/room_downsync_frame.pb.go +++ b/battle_srv/protos/room_downsync_frame.pb.go @@ -1618,6 +1618,77 @@ func (x *RoomDownsyncFrame) GetBulletLocalIdCounter() int32 { return 0 } +type HolePunchUpsync struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + JoinIndex int32 `protobuf:"varint,1,opt,name=joinIndex,proto3" json:"joinIndex,omitempty"` + IntAuthToken string `protobuf:"bytes,2,opt,name=intAuthToken,proto3" json:"intAuthToken,omitempty"` + BoundRoomId int32 `protobuf:"varint,3,opt,name=boundRoomId,proto3" json:"boundRoomId,omitempty"` + AuthKey int32 `protobuf:"varint,4,opt,name=authKey,proto3" json:"authKey,omitempty"` +} + +func (x *HolePunchUpsync) Reset() { + *x = HolePunchUpsync{} + if protoimpl.UnsafeEnabled { + mi := &file_room_downsync_frame_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HolePunchUpsync) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HolePunchUpsync) ProtoMessage() {} + +func (x *HolePunchUpsync) ProtoReflect() protoreflect.Message { + mi := &file_room_downsync_frame_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HolePunchUpsync.ProtoReflect.Descriptor instead. +func (*HolePunchUpsync) Descriptor() ([]byte, []int) { + return file_room_downsync_frame_proto_rawDescGZIP(), []int{12} +} + +func (x *HolePunchUpsync) GetJoinIndex() int32 { + if x != nil { + return x.JoinIndex + } + return 0 +} + +func (x *HolePunchUpsync) GetIntAuthToken() string { + if x != nil { + return x.IntAuthToken + } + return "" +} + +func (x *HolePunchUpsync) GetBoundRoomId() int32 { + if x != nil { + return x.BoundRoomId + } + return 0 +} + +func (x *HolePunchUpsync) GetAuthKey() int32 { + if x != nil { + return x.AuthKey + } + return 0 +} + var File_room_downsync_frame_proto protoreflect.FileDescriptor var file_room_downsync_frame_proto_rawDesc = []byte{ @@ -1968,8 +2039,17 @@ var file_room_downsync_frame_proto_rawDesc = []byte{ 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x83, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x62, 0x75, 0x6c, 0x6c, 0x65, 0x74, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, - 0x42, 0x13, 0x5a, 0x11, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x73, 0x72, 0x76, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x22, 0x8f, 0x01, 0x0a, 0x0f, 0x48, 0x6f, 0x6c, 0x65, 0x50, 0x75, 0x6e, 0x63, 0x68, 0x55, 0x70, + 0x73, 0x79, 0x6e, 0x63, 0x12, 0x1c, 0x0a, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6a, 0x6f, 0x69, 0x6e, 0x49, 0x6e, 0x64, + 0x65, 0x78, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x69, 0x6e, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, + 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x75, 0x74, 0x68, + 0x4b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x61, 0x75, 0x74, 0x68, 0x4b, + 0x65, 0x79, 0x42, 0x13, 0x5a, 0x11, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x5f, 0x73, 0x72, 0x76, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1984,7 +2064,7 @@ func file_room_downsync_frame_proto_rawDescGZIP() []byte { return file_room_downsync_frame_proto_rawDescData } -var file_room_downsync_frame_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_room_downsync_frame_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_room_downsync_frame_proto_goTypes = []interface{}{ (*PlayerDownsync)(nil), // 0: protos.PlayerDownsync (*InputFrameDecoded)(nil), // 1: protos.InputFrameDecoded @@ -1998,6 +2078,7 @@ var file_room_downsync_frame_proto_goTypes = []interface{}{ (*FireballBullet)(nil), // 9: protos.FireballBullet (*BattleColliderInfo)(nil), // 10: protos.BattleColliderInfo (*RoomDownsyncFrame)(nil), // 11: protos.RoomDownsyncFrame + (*HolePunchUpsync)(nil), // 12: protos.HolePunchUpsync } var file_room_downsync_frame_proto_depIdxs = []int32{ 2, // 0: protos.WsReq.inputFrameUpsyncBatch:type_name -> protos.InputFrameUpsync @@ -2166,6 +2247,18 @@ func file_room_downsync_frame_proto_init() { return nil } } + file_room_downsync_frame_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HolePunchUpsync); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -2173,7 +2266,7 @@ func file_room_downsync_frame_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_room_downsync_frame_proto_rawDesc, NumEnums: 0, - NumMessages: 12, + NumMessages: 13, NumExtensions: 0, NumServices: 0, }, diff --git a/frontend/assets/resources/pbfiles/room_downsync_frame.proto b/frontend/assets/resources/pbfiles/room_downsync_frame.proto index 3b16996..be466ea 100644 --- a/frontend/assets/resources/pbfiles/room_downsync_frame.proto +++ b/frontend/assets/resources/pbfiles/room_downsync_frame.proto @@ -208,3 +208,10 @@ message RoomDownsyncFrame { int32 bulletLocalIdCounter = 1027; } + +message HolePunchUpsync { + int32 joinIndex = 1; + string intAuthToken = 2; + int32 boundRoomId = 3; + int32 authKey = 4; +} diff --git a/frontend/assets/scenes/offline_map.fire b/frontend/assets/scenes/offline_map.fire index 702274e..58b6939 100644 --- a/frontend/assets/scenes/offline_map.fire +++ b/frontend/assets/scenes/offline_map.fire @@ -547,7 +547,7 @@ "array": [ 0, 0, - 210.25627653647612, + 210.43935996345485, 0, 0, 0, diff --git a/frontend/assets/scripts/OfflineMap.js b/frontend/assets/scripts/OfflineMap.js index 2720a9b..ae7d85b 100644 --- a/frontend/assets/scripts/OfflineMap.js +++ b/frontend/assets/scripts/OfflineMap.js @@ -147,7 +147,14 @@ cc.Class({ if (cc.sys.isNative) { DelayNoMore.UdpSession.upsertPeerUdpAddr(self.selfPlayerInfo.JoinIndex, "192.168.31.194", 6789, 123456); const res1 = DelayNoMore.UdpSession.openUdpSession(8888 + self.selfPlayerInfo.JoinIndex); - //const res2 = DelayNoMore.UdpSession.closeUdpSession(); + const holePunchDate = window.pb.protos.HolePunchUpsync.encode({ + joinIndex: self.selfPlayerInfo.JoinIndex, + boundRoomId: 22, + intAuthToken: "foobar", + authKey: Math.floor(Math.random() * 65535), + }).finish() + const res2 = DelayNoMore.UdpSession.punchToServer(holePunchDate); + //const res3 = DelayNoMore.UdpSession.closeUdpSession(); } self.onRoomDownsyncFrame(startRdf); diff --git a/frontend/assets/scripts/modules/room_downsync_frame_proto_bundle.forcemsg.js b/frontend/assets/scripts/modules/room_downsync_frame_proto_bundle.forcemsg.js index 566c815..269e6e0 100644 --- a/frontend/assets/scripts/modules/room_downsync_frame_proto_bundle.forcemsg.js +++ b/frontend/assets/scripts/modules/room_downsync_frame_proto_bundle.forcemsg.js @@ -6916,6 +6916,279 @@ $root.protos = (function() { return RoomDownsyncFrame; })(); + protos.HolePunchUpsync = (function() { + + /** + * Properties of a HolePunchUpsync. + * @memberof protos + * @interface IHolePunchUpsync + * @property {number|null} [joinIndex] HolePunchUpsync joinIndex + * @property {string|null} [intAuthToken] HolePunchUpsync intAuthToken + * @property {number|null} [boundRoomId] HolePunchUpsync boundRoomId + * @property {number|null} [authKey] HolePunchUpsync authKey + */ + + /** + * Constructs a new HolePunchUpsync. + * @memberof protos + * @classdesc Represents a HolePunchUpsync. + * @implements IHolePunchUpsync + * @constructor + * @param {protos.IHolePunchUpsync=} [properties] Properties to set + */ + function HolePunchUpsync(properties) { + if (properties) + for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * HolePunchUpsync joinIndex. + * @member {number} joinIndex + * @memberof protos.HolePunchUpsync + * @instance + */ + HolePunchUpsync.prototype.joinIndex = 0; + + /** + * HolePunchUpsync intAuthToken. + * @member {string} intAuthToken + * @memberof protos.HolePunchUpsync + * @instance + */ + HolePunchUpsync.prototype.intAuthToken = ""; + + /** + * HolePunchUpsync boundRoomId. + * @member {number} boundRoomId + * @memberof protos.HolePunchUpsync + * @instance + */ + HolePunchUpsync.prototype.boundRoomId = 0; + + /** + * HolePunchUpsync authKey. + * @member {number} authKey + * @memberof protos.HolePunchUpsync + * @instance + */ + HolePunchUpsync.prototype.authKey = 0; + + /** + * Creates a new HolePunchUpsync instance using the specified properties. + * @function create + * @memberof protos.HolePunchUpsync + * @static + * @param {protos.IHolePunchUpsync=} [properties] Properties to set + * @returns {protos.HolePunchUpsync} HolePunchUpsync instance + */ + HolePunchUpsync.create = function create(properties) { + return new HolePunchUpsync(properties); + }; + + /** + * Encodes the specified HolePunchUpsync message. Does not implicitly {@link protos.HolePunchUpsync.verify|verify} messages. + * @function encode + * @memberof protos.HolePunchUpsync + * @static + * @param {protos.HolePunchUpsync} message HolePunchUpsync message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + HolePunchUpsync.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.joinIndex != null && Object.hasOwnProperty.call(message, "joinIndex")) + writer.uint32(/* id 1, wireType 0 =*/8).int32(message.joinIndex); + if (message.intAuthToken != null && Object.hasOwnProperty.call(message, "intAuthToken")) + writer.uint32(/* id 2, wireType 2 =*/18).string(message.intAuthToken); + if (message.boundRoomId != null && Object.hasOwnProperty.call(message, "boundRoomId")) + writer.uint32(/* id 3, wireType 0 =*/24).int32(message.boundRoomId); + if (message.authKey != null && Object.hasOwnProperty.call(message, "authKey")) + writer.uint32(/* id 4, wireType 0 =*/32).int32(message.authKey); + return writer; + }; + + /** + * Encodes the specified HolePunchUpsync message, length delimited. Does not implicitly {@link protos.HolePunchUpsync.verify|verify} messages. + * @function encodeDelimited + * @memberof protos.HolePunchUpsync + * @static + * @param {protos.HolePunchUpsync} message HolePunchUpsync message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + HolePunchUpsync.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a HolePunchUpsync message from the specified reader or buffer. + * @function decode + * @memberof protos.HolePunchUpsync + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {protos.HolePunchUpsync} HolePunchUpsync + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + HolePunchUpsync.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + var end = length === undefined ? reader.len : reader.pos + length, message = new $root.protos.HolePunchUpsync(); + while (reader.pos < end) { + var tag = reader.uint32(); + switch (tag >>> 3) { + case 1: { + message.joinIndex = reader.int32(); + break; + } + case 2: { + message.intAuthToken = reader.string(); + break; + } + case 3: { + message.boundRoomId = reader.int32(); + break; + } + case 4: { + message.authKey = reader.int32(); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a HolePunchUpsync message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof protos.HolePunchUpsync + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {protos.HolePunchUpsync} HolePunchUpsync + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + HolePunchUpsync.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a HolePunchUpsync message. + * @function verify + * @memberof protos.HolePunchUpsync + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + HolePunchUpsync.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.joinIndex != null && message.hasOwnProperty("joinIndex")) + if (!$util.isInteger(message.joinIndex)) + return "joinIndex: integer expected"; + if (message.intAuthToken != null && message.hasOwnProperty("intAuthToken")) + if (!$util.isString(message.intAuthToken)) + return "intAuthToken: string expected"; + if (message.boundRoomId != null && message.hasOwnProperty("boundRoomId")) + if (!$util.isInteger(message.boundRoomId)) + return "boundRoomId: integer expected"; + if (message.authKey != null && message.hasOwnProperty("authKey")) + if (!$util.isInteger(message.authKey)) + return "authKey: integer expected"; + return null; + }; + + /** + * Creates a HolePunchUpsync message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof protos.HolePunchUpsync + * @static + * @param {Object.} object Plain object + * @returns {protos.HolePunchUpsync} HolePunchUpsync + */ + HolePunchUpsync.fromObject = function fromObject(object) { + if (object instanceof $root.protos.HolePunchUpsync) + return object; + var message = new $root.protos.HolePunchUpsync(); + if (object.joinIndex != null) + message.joinIndex = object.joinIndex | 0; + if (object.intAuthToken != null) + message.intAuthToken = String(object.intAuthToken); + if (object.boundRoomId != null) + message.boundRoomId = object.boundRoomId | 0; + if (object.authKey != null) + message.authKey = object.authKey | 0; + return message; + }; + + /** + * Creates a plain object from a HolePunchUpsync message. Also converts values to other types if specified. + * @function toObject + * @memberof protos.HolePunchUpsync + * @static + * @param {protos.HolePunchUpsync} message HolePunchUpsync + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + HolePunchUpsync.toObject = function toObject(message, options) { + if (!options) + options = {}; + var object = {}; + if (options.defaults) { + object.joinIndex = 0; + object.intAuthToken = ""; + object.boundRoomId = 0; + object.authKey = 0; + } + if (message.joinIndex != null && message.hasOwnProperty("joinIndex")) + object.joinIndex = message.joinIndex; + if (message.intAuthToken != null && message.hasOwnProperty("intAuthToken")) + object.intAuthToken = message.intAuthToken; + if (message.boundRoomId != null && message.hasOwnProperty("boundRoomId")) + object.boundRoomId = message.boundRoomId; + if (message.authKey != null && message.hasOwnProperty("authKey")) + object.authKey = message.authKey; + return object; + }; + + /** + * Converts this HolePunchUpsync to JSON. + * @function toJSON + * @memberof protos.HolePunchUpsync + * @instance + * @returns {Object.} JSON object + */ + HolePunchUpsync.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for HolePunchUpsync + * @function getTypeUrl + * @memberof protos.HolePunchUpsync + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + HolePunchUpsync.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/protos.HolePunchUpsync"; + }; + + return HolePunchUpsync; + })(); + return protos; })(); diff --git a/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session.cpp b/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session.cpp index 6f9f56b..10958bd 100644 --- a/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session.cpp +++ b/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session.cpp @@ -4,9 +4,12 @@ #include "uv/uv.h" #include -static uv_udp_t* udpSocket = NULL; +uv_udp_t* udpSocket = NULL; uv_loop_t* loop = NULL; // Only this loop is used for this simple PoC +int const sendBufferLen = 1024; +uv_mutex_t sendLock, recvLock; + void _onRead(uv_udp_t* req, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) { if (nread < 0) { CCLOGERROR("Read error %s", uv_err_name(nread)); @@ -32,9 +35,13 @@ static void _allocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* b void startRecvLoop(void* arg) { uv_loop_t* loop = (uv_loop_t*)arg; uv_run(loop, UV_RUN_DEFAULT); + CCLOG("UDP session is ended!"); } bool DelayNoMore::UdpSession::openUdpSession(int port) { + uv_mutex_init(&sendLock); + uv_mutex_init(&recvLock); + CCLOG("About to open UDP session at port=%d...", port); loop = uv_loop_new(); // Only the default loop is used for this simple PoC udpSocket = (uv_udp_t*)malloc(sizeof(uv_udp_t)); @@ -48,19 +55,6 @@ bool DelayNoMore::UdpSession::openUdpSession(int port) { uv_thread_t recvTid; uv_thread_create(&recvTid, startRecvLoop, loop); - - //std::thread([=]() { - // udpSocket = (uv_udp_t*)malloc(sizeof(uv_udp_t)); - // SOCKADDR_IN recv_addr; - // uv_ip4_addr("0.0.0.0", port, &recv_addr); - // - // uv_udp_init(loop, udpSocket); - // - // uv_udp_bind(udpSocket, (struct sockaddr const*)&recv_addr, UV_UDP_REUSEADDR); - // uv_udp_recv_start(udpSocket, _allocBuffer, _onRead); - // - // startRecvLoop(loop); - //}).detach(); CCLOG("Finished opening UDP session at port=%d", port); @@ -79,6 +73,9 @@ bool DelayNoMore::UdpSession::closeUdpSession() { uv_loop_close(loop); free(udpSocket); free(loop); + + uv_mutex_destroy(&sendLock); + uv_mutex_destroy(&recvLock); CCLOG("Closed udp session and dealloc all resources..."); return true; @@ -104,3 +101,22 @@ void DelayNoMore::UdpSession::onMessage(BYTEC* const bytes) { } } } + +void _onSend(uv_udp_send_t* req, int status) { + free(req); + if (status) { + fprintf(stderr, "uv_udp_send_cb error: %s\n", uv_strerror(status)); + } +} + +bool DelayNoMore::UdpSession::punchToServer(BYTEC* const bytes) { + uv_mutex_lock(&sendLock); + uv_udp_send_t* req = (uv_udp_send_t*)malloc(sizeof(uv_udp_send_t)); + uv_buf_t sendBuffer = uv_buf_init(bytes, sizeof bytes); // [WARNING] The RAM space used for "bytes", either on stack or in heap, is preallocated and managed by the caller. + + SOCKADDR_IN destAddr; + uv_ip4_addr("127.0.0.1", 3000, &destAddr); + uv_udp_send(req, udpSocket, &sendBuffer, 1, (struct sockaddr const*)&destAddr, _onSend); + uv_mutex_unlock(&sendLock); + return true; +} \ No newline at end of file diff --git a/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session.hpp b/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session.hpp index 68de374..0e68091 100644 --- a/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session.hpp +++ b/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session.hpp @@ -3,7 +3,7 @@ #include "cocos/scripting/js-bindings/jswrapper/SeApi.h" -typedef unsigned char const BYTEC; +typedef char BYTEC; typedef char const CHARC; namespace DelayNoMore { @@ -13,7 +13,7 @@ namespace DelayNoMore { static bool closeUdpSession(); static bool upsertPeerUdpAddr(int joinIndex, CHARC* const ip, int port, uint32_t authKey); //static bool clearPeerUDPAddrList(); - //static void punchToServer(CBYTE* const bytes); + static bool punchToServer(BYTEC* const bytes); static void onMessage(BYTEC* const bytes); }; } diff --git a/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session_bridge.cpp b/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session_bridge.cpp index c0bc444..9c2b3f8 100644 --- a/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session_bridge.cpp +++ b/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session_bridge.cpp @@ -6,17 +6,35 @@ bool openUdpSession(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); CC_UNUSED bool ok = true; - if (1 == argc) { + if (1 == argc && args[0].isNumber()) { SE_PRECONDITION2(ok, false, "openUdpSession: Error processing arguments"); int port = args[0].toInt32(); return DelayNoMore::UdpSession::openUdpSession(port); } - SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1); + SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d; or wrong arg type!", (int)argc, 1); return false; } SE_BIND_FUNC(openUdpSession) +bool punchToServer(se::State& s) { + const auto& args = s.args(); + size_t argc = args.size(); + CC_UNUSED bool ok = true; + if (1 == argc && args[0].isObject() && args[0].toObject()->isTypedArray()) { + SE_PRECONDITION2(ok, false, "punchToServer: Error processing arguments"); + BYTEC bytes[1024]; + memset(bytes, 0, sizeof bytes); + se::Object* obj = args[0].toObject(); + size_t sz = 0; + obj->getTypedArrayData((uint8_t**)&bytes, &sz); + return DelayNoMore::UdpSession::punchToServer(bytes); + } + SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d; or wrong arg type!", (int)argc, 1); + return false; +} +SE_BIND_FUNC(punchToServer) + bool closeUdpSession(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); @@ -35,7 +53,7 @@ bool upsertPeerUdpAddr(se::State& s) { const auto& args = s.args(); size_t argc = args.size(); CC_UNUSED bool ok = true; - if (4 == argc) { + if (4 == argc && args[0].isNumber() && args[1].isString() && args[2].isNumber() && args[3].isNumber()) { SE_PRECONDITION2(ok, false, "upsertPeerUdpAddr: Error processing arguments"); int joinIndex = args[0].toInt32(); CHARC* ip = args[1].toString().c_str(); @@ -43,7 +61,7 @@ bool upsertPeerUdpAddr(se::State& s) { uint32_t authKey = args[3].toUint32(); return DelayNoMore::UdpSession::upsertPeerUdpAddr(joinIndex, ip, port, authKey); } - SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 4); + SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d; or wrong arg type!", (int)argc, 4); return false; } @@ -79,6 +97,7 @@ bool registerUdpSession(se::Object* obj) auto cls = se::Class::create("UdpSession", ns, nullptr, nullptr); cls->defineStaticFunction("openUdpSession", _SE(openUdpSession)); + cls->defineStaticFunction("punchToServer", _SE(punchToServer)); cls->defineStaticFunction("closeUdpSession", _SE(closeUdpSession)); cls->defineStaticFunction("upsertPeerUdpAddr", _SE(upsertPeerUdpAddr)); cls->defineFinalizeFunction(_SE(udpSessionFinalize)); diff --git a/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session_bridge.hpp b/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session_bridge.hpp index 7cc3db5..dee035d 100644 --- a/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session_bridge.hpp +++ b/frontend/build-templates/jsb-link/frameworks/runtime-src/Classes/udp_session_bridge.hpp @@ -11,6 +11,7 @@ extern se::Class* __jsb_udp_session_class; bool registerUdpSession(se::Object* obj); SE_DECLARE_FUNC(openUdpSession); +SE_DECLARE_FUNC(punchToServer); SE_DECLARE_FUNC(closeUdpSession); SE_DECLARE_FUNC(upsertPeerUdpAddr); diff --git a/frontend/settings/builder.json b/frontend/settings/builder.json index 98b6942..4245ee4 100644 --- a/frontend/settings/builder.json +++ b/frontend/settings/builder.json @@ -17,7 +17,8 @@ }, "encryptJs": false, "excludeScenes": [ - "8491a86c-bec9-4813-968a-128ca01639e0" + "92160186-3e0d-4e0a-ae20-97286170ba58", + "2ff474d9-0c9e-4fe3-87ec-fbff7cae85b4" ], "fb-instant-games": {}, "includeSDKBox": false, @@ -37,7 +38,7 @@ "REMOTE_SERVER_ROOT": "", "orientation": "portrait" }, - "startScene": "2ff474d9-0c9e-4fe3-87ec-fbff7cae85b4", + "startScene": "8491a86c-bec9-4813-968a-128ca01639e0", "title": "DelayNoMore", "webOrientation": "landscape", "wechatgame": { diff --git a/udp_server_prac/main.go b/udp_server_prac/main.go new file mode 100644 index 0000000..600613b --- /dev/null +++ b/udp_server_prac/main.go @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + "net" + "strings" +) + +func main() { + conn, err := net.ListenUDP("udp", &net.UDPAddr{ + Port: 3000, + IP: net.ParseIP("127.0.0.1"), + }) + if err != nil { + panic(err) + } + + defer conn.Close() + fmt.Printf("server listening %s\n", conn.LocalAddr().String()) + + for { + message := make([]byte, 2046) + rlen, remote, err := conn.ReadFromUDP(message[:]) + if err != nil { + panic(err) + } + + data := strings.TrimSpace(string(message[:rlen])) + fmt.Printf("received: %s from %s\n", data, remote) + } +}