Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use ConcreateExtensionField? #162

Open
poixen opened this issue Aug 1, 2016 · 13 comments
Open

How to use ConcreateExtensionField? #162

poixen opened this issue Aug 1, 2016 · 13 comments
Labels

Comments

@poixen
Copy link

poixen commented Aug 1, 2016

Question

How do you use ConcreateExtensionField?
I am having a hard time creating a new instance. There is not documentation on its use apart from the variable names in the init call.
There are also no gitter chat rooms to communicate, or a forum. This is the only way I can contact.

@alexeyxo
Copy link
Owner

alexeyxo commented Aug 1, 2016

You can see in file named TestUtilities.swift. For example setPackedExtensions method.

@poixen
Copy link
Author

poixen commented Aug 1, 2016

I can see in TestUtilities.swift::setPackedExtentions that you use:

try message.addExtension(ProtobufUnittest.UnittestRoot.packedInt32Extension(), value:Int32(601))

This adds a ConcreateExtensionField from ProtobufUnittest.UnittestRoot.packedInt32Extension() but I can not find this method. I need to see how a ConcreateExtensionField is made so that I can do:

let e = ConcreateExtensionField(type: ExtensionType.ExtensionTypeMessage, extendedClass: ?????, 
fieldNumber: Int32(1001), defaultValue: ?????, messageOrGroupClass: ?????, 
isRepeated: false, isPacked: false, isMessageSetWireFormat: false)
builder.getExtension(e)

@alexeyxo
Copy link
Owner

alexeyxo commented Aug 1, 2016

Extensions are automatically generated. You can't use them without descriptions in ".proto" file.

@poixen
Copy link
Author

poixen commented Aug 1, 2016

Maybe I misunderstand how to get an extension then?
If I have a builder and I want to return an extension, what is the best way to do it?

@alexeyxo
Copy link
Owner

alexeyxo commented Aug 1, 2016

Get me your .proto file with extensions.

@poixen
Copy link
Author

poixen commented Aug 1, 2016

commands.proto (original file has some additional repeated XXXXCommands but I just need SessionCommand working for now)

import "session_commands.proto";

message CommandContainer {
optional uint64 cmd_id = 1;

optional uint32 game_id = 10;
optional uint32 room_id = 20;

repeated SessionCommand session_command = 100;
}

session_commands.proto (Again, original has more, this is slim version)

syntax = "proto2";

message SessionCommand {
enum SessionCommandType {
LOGIN = 1001;
}
extensions 100 to max;
}


message Command_Login {
extend SessionCommand {
optional Command_Login ext = 1001;
}
optional string user_name = 1;
optional string password = 2;
optional string clientid = 3;
optional string clientver = 4;
repeated string clientfeatures = 5;
}

So I need to get the CommandLogin from the SessionCommand.

@poixen
Copy link
Author

poixen commented Aug 1, 2016

Please dont tell me its only sessionCommandBuilder.getExtension(CommandLogin.ext())

Update:

let sessionCommandBuilder = SessionCommand.Builder()
et ext = sessionCommandBuilder.getExtension(CommandLogin.ext()) as! CommandLogin
// fill the login extention
ext.clientid = "asdf" // doesnt work as var is immutable

I need to get the builder from the extension instead.

@poixen
Copy link
Author

poixen commented Aug 1, 2016

How does this look?

// build the command container
        NSLog("Building Command_Container...")
        let commandContainerBuilder = CommandContainer.Builder()
        commandContainerBuilder.cmdId = UInt64(cmdId+=1)
        do {
            NSLog("Building SessionCommand...")
            let sessionCommandBuilder = SessionCommand.Builder()
            NSLog("Setting Command_Login to SessionCommand Builder...")
            try sessionCommandBuilder.setExtension(CommandLogin.ext(), value: commandLogin)
            NSLog("Building SessionCommand...")
            let sessionCommand = try sessionCommandBuilder.build()
            NSLog("SessionCommand built!")
            NSLog("Appending SessionCommand to CommandContainer Builder...")
            commandContainerBuilder.sessionCommand.append(sessionCommand)
        } catch {
            print("Error trying to merge from Command_Login. info: \(error)")
            return
        }
        let commandContainer : CommandContainer?
        do {
            commandContainer = try commandContainerBuilder.build()
            NSLog("CommandContainer built!")
        } catch {
            print("Error trying to build a Command_Container. info: \(error)")
            return
        }

@alexeyxo
Copy link
Owner

alexeyxo commented Aug 2, 2016

I don't understand, where you have problems?

@poixen
Copy link
Author

poixen commented Aug 2, 2016

Sorry for the late reply. I have been investigating.
I have managed to create the correct protobuf message to log into the server! 🎉

I have now come to a new issue, dealing with the response.
I am porting this javascript client code to swift:

        // Response/event received, decode to a ServerMessage
         var msg = WebClient.pb.ServerMessage.decode(event.data);

        // in switch statement:
         case WebClient.pb.ServerMessage.MessageType.SESSION_EVENT:
         WebClient.processSessionEvent(msg.sessionEvent);

         // in processSessionEvent() we access the data:
         raw[".Event_ServerMessage.ext"]["message"];

I have come up with the following in swift:

let serverMessage = try ServerMessage.parseFromData(data)
switch (serverMessage.messageType) {
            case ServerMessage.MessageType.SessionEvent:
                let splitString = serverMessage.sessionEvent!.description.componentsSeparatedByString(":")
                NSLog("SessionEvent Code: \(splitString[0])")
                NSLog("SessionEvent Data: \(splitString[1])")

                let eventServerId = serverMessage.sessionEvent.getExtension(EventServerIdentification.ext()) as! EventServerIdentification
                NSLog("Server Name: \(eventServerId.serverName)")
                NSLog("Server Version: \(eventServerId.serverName)")
                NSLog("Server Protocol Version: \(eventServerId.protocolVersion)")
                break
            default:
                break
            }

Which gives the output:

SessionEvent Code: 500
SessionEvent Data:  <0a1d576f 6f676572 776f726b 7320436f 636b6174 72696365 20536572 76657212 14643832 35363464 20283230 31362d30 372d3135 29180e>
 Server Name: 
Server Version: 
Server Protocol Version: 0

The output hex data is the Server Name, Server Version and Server Protocol Version.

Why cant I get the EventServerIdentification values? Am I doing something wrong?
Does this line look weird? let eventServerId = serverMessage.sessionEvent.getExtension(EventServerIdentification.ext()) as! EventServerIdentification

Here is the server_message.proto

import "session_event.proto";

message ServerMessage {
enum MessageType {
SESSION_EVENT = 1;
}
optional MessageType message_type = 1;

optional SessionEvent session_event = 3;
}

Here is the session_event.proto

message SessionEvent {
enum SessionEventType {
SERVER_IDENTIFICATION = 500;
SERVER_COMPLETE_LIST = 600;
SERVER_MESSAGE = 1000;
SERVER_SHUTDOWN = 1001;
CONNECTION_CLOSED = 1002;
USER_MESSAGE = 1003;
LIST_ROOMS = 1004;
ADD_TO_LIST = 1005;
REMOVE_FROM_LIST = 1006;
USER_JOINED = 1007;
USER_LEFT = 1008;
GAME_JOINED = 1009;
NOTIFY_USER = 1010;
REPLAY_ADDED = 1100;
}
extensions 100 to max;
}

Here is the event_server_identification.proto

import "session_event.proto";

message Event_ServerIdentification {
extend SessionEvent {
optional Event_ServerIdentification ext = 500;
}
optional string server_name = 1;
optional string server_version = 2;
optional uint32 protocol_version = 3;
}

@Daenyth
Copy link

Daenyth commented Aug 3, 2016

Chiming in - try dropping the first 60 bytes from the server, there's an xml header intended for clients that were written before the switch to protobuf. Discarding those bytes then decoding should give you a correct message.

Nevermind, this is not true for the port you're using.

@poixen
Copy link
Author

poixen commented Aug 3, 2016

Thanks the the reply.
@alexeyxo Daenyth is from a project I work on. The 60 bytes onlly comes over a certain port, and I am not using that one.

We still need to know if this is the syntactically correct:

let eventServerId = serverMessage.sessionEvent.getExtension(EventServerIdentification.ext()) as! EventServerIdentification

@poixen
Copy link
Author

poixen commented Aug 3, 2016

@alexeyxo If you are around you confirm if this is the correct way to work with Extensions, that would be great. Its a real blocker for me :/

let eventServerId = serverMessage.sessionEvent.getExtension(EventServerIdentification.ext()) as! EventServerIdentification

Edit:
Added debug screen.

screen shot 2016-08-03 at 20 53 08

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants