分享
 
 
 

SoulSeek Protocol

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

SoulSeek Protocol DocumentationTable of ContentsVersion History

Introduction

Overview

Constants

Messages

Server Messages

Peer Messages

Message Sequences

Version History2003-10-05: Added integer to the Login message containing the IP of the client. Arend van Beelen jr.

2003-10-04: Correct statement about Soulseek message byte-ordering. They are little-endian. Robert Sayre

2003-03-16: Added PierceFW message summary, added to PlaceInQueueRequest message summary, Robert Sayre

2003-01-26: Added peer messages and login sequence, had revelation about reusing existing peer socket from search result for file request, BriEnigma

2003-01-20: Initial revision, BriEnigma

CVS version ID: $Id: protocol.html,v 1.11 2003/10/12 19:23:18 franklinmint Exp $

Mental Note: When updating this document, remember to upload the latest version to the SourceForge project documentation web page. IntroductionThe SoulSeek protocol is not officially documented anywhere. This document is the result of effort by members of the SoleSeek project team. It was pieced together by examining the Python SoulSeek source code, as well as sniffing network packets. (Hey, Nir! Please don't sue us inder the DMCA for reverse engineering the protocol!) This document should not be considered the official specification. It is our best guess at how the protocol works.

OverviewThe SoulSeek protocol consists of a finite number of messages. Some of these messages are used for communicating between the client and server. Others are used for communications between a client and a peer (another client). All of these messages (with the exception of a couple of peer messages TODO:...are PeerInit and PierceFW the only exceptions?...) follow a standard format.

There are a few datatypes that the message blocks use:

(TODO: endian-ness? I always get mixed up.)

Integer

4 bytes, little endian

Byte

1 byte

String

an integer (4 bytes) that specifies the length of the string, followed by the string data as 8-bit characters. The string is not null-terminated.

TODO:

are other datatypes used?

The standard message blocks start with an integer. This integer defines the size of the message payload--everything contained in the message, but not including the 4-bytes length. The payload starts with an integer that we shall call the message code that describes what type of message this is. The datatype and meaning of the remaining payload data is dependant on the message code. For example, the following is a very simple message, the Login message from the client to the server:

Message Length

Message Payload

4-byte-integer: 30

4-byte-integer: 1

4-byte-integer: 8

J

o

h

n

G

a

l

t

4-byte-integer: 6

s

e

c

r

e

t

4-byte-integer: 200

Message Code 1 == "Login" (4 bytes)

String, length 8 (12 bytes)

String, length 6 (10 bytes)

Version (4 bytes)

This sends a message to the server with message code 1. Since message code 1 is the Login message, the server knows to expect two strings and an integer. The fist string, we can see is of length 8 and contains the letters "JohnGalt". The second string is of length 6 and contains the letters "secret". The remaining integer is the number 200.

It is worth noting that messages with the same code may have different payloads, depending on the direction of the message: client-to-server (generally, a request) or server-to-client (generally, a response). In the above example, the message is a Login message from the client to the server. The server responds to the client with message that also has the message code 1 ("Login"), but has a different payload. Login messages originating at the server (we can think of it as a Login response message) contain a byte (1/0 for success/fail) followed by a string (a message about the results of the login or a server greeting).

ConstantsThe SoulSeek protocol makes use of several constants:

Status Codes

-1

Unknown

0

Offline

1

Away

2

Online

Transfer Direction

0

Download

1

Upload

TODO: There are probably more...

MessagesJump directly to a server message: Login:1 SetWaitPort:2 GetPeerAddress:3 AddUser:5 GetUserStatus:7 SayChatroom:13 JoinRoom:14 LeaveRoom:15 UserJoinedRoom:16 UserLeftRoom:17 ConnectToPeer:18 MessageUser:22 MessageAcked:23 FileSearch:26 SetStatus:28 SharedFoldersFiles:35 GetUserStats:36 QueuedDownloads:40 PlaceInLineResponse:60 RoomAdded:62 RoomRemoved:63 RoomList:64 ExactFileSearch:65 AdminMessage:66 GlobalUserList:67 TunneledMessage:68 PrivilegedUsers:69 AddToPrivileged:91 CheckPrivileges:92 CantConnectToPeer:1001

Jump directly to a peer message: PeerInit PierceFW GetSharedFileList:4 SharedFileList:5 FileSearchResult:9 UserInfoRequest:15 UserInfoReply:16 FolderContentsRequest:36 FolderContentsResponse:37 TransferRequest:40 TransferResponse:41 PlaceholdUpload:42 QueueUpload:43 PlaceInQueue:44 UploadFailed:46 QueueFailed:50 PlaceInQueueRequest:51

Server MessagesLogin:1Client-to-Server (attempt to login)

integer

1 (Message Code)

string

Username

string

Password

integer

Version

Server-to-Client (login success/fail)

integer

1 (Message Code)

byte

success (0=fail, 1=success)

string

Login message (error message or greeting message)

integer

Optional integer containing the external IPv4 address of the client. Only sent if the login was successful.

SetWaitPort:2Client-to-Server

This is sent to the server to tell it what port we are listening on.

integer

2 (Message Code)

integer

port number (generally 2234)

Server-to-Client

It is believed that SetWaitPort messages are not sent from the server to the client.

GetPeerAddress:3Client-to-Server

This is sent to the server to ask for a peer's address (IP address and port), given the peer's username.

integer

3 (Message Code)

string

username

Server-to-Client

This is the response from the server.

integer

3 (Message Code)

string

username this address belongs to

integer

IP address

integer

port number

AddUser:5Client-to-Server

This message is sent when you want to start monitoring the online status of a user. Once we start "watching" a user by sending this message, the server will send (TODO: is the message AddUser or GetUserStatus) messages to us whenever the user changes status (away, back, offline, etc).

Note: There also seems to be a GetPeerAddress response message returned automatically, along with the AddUser response message--even though the GetPeerAddress request was never made. Can anyone confirm this?

integer

5 (Message Code)

string

username to start watching

Server-to-Client

integer

5 (Message Code)

string

username being watching

byte

whether the user exists

GetUserStatus:7Client-to-Server

This message is used to request a user's current status.

integer

7 (Message Code)

string

username to get status of

Server-to-client

This message is used by the server to report back to us a user's current status. integer

7 (Message Code)

string

username this status applies to

integer

status code, see above

SayChatroom:13Client-to-Server

This message is sent to say something in a chatroom.

integer

13 (Message Code)

string

room

string

message

Server-to-Client

Somebody said something in a chatroom we are in.

integer

13 (Message Code)

string

room

string

username

string

message

JoinRoom:14Client-to-Server

We would like to join a chatroom.

integer

14 (Message Code)

string

room

Server-to-Client

We have joined the room. Here is a list of all the people in the room. (This could very easily be a giant set of data!)

integer

14 (Message Code)

string

room

integer

number of users in this room

string

username #1

string

username #2

:

:

string

username #n

integer

number of status code intgers (should be the same as number of users in the above field)

integer

status code of username #1

integer

status code of username #2

:

:

integer

status code of username #n

integer

number of statistics records (should be the same as number of users in the above field)

integer

stats record 1: avgspeed of username #1

integer

stats record 1: downloadnum of username #1

integer

stats record 1: something of username #1

integer

stats record 1: files of username #1

integer

stats record 1: dirs of username #1

integer

stats record 2: avgspeed of username #2

integer

stats record 2: downloadnum of username #2

integer

stats record 2: something of username #2

integer

stats record 2: files of username #2

integer

stats record 2: dirs of username #2

:

:

integer

stats record n: avgspeed of username #n

integer

stats record n: downloadnum of username #n

integer

stats record n: something of username #n

integer

stats record n: files of username #n

integer

stats record n: dirs of username #n

integer

number of slotsfull records

integer

slotsfull field of username #1

integer

slotsfull field of username #2

:

:

integer

slotsfull field of username #n

LeaveRoom:15Client-to-Server

We would like to leave a chatroom.

integer

15 (Message Code)

string

room

Server-to-Client

Server tells us we have left the room. Note that, in theory, this could happen at any time--it may not necessarily be a response to a LeaveRoom message. It is entirely possible that the server could send this to kick you out of a room (although this author has never seen it happen).

integer

15 (Message Code)

string

room

UserJoinedRoom:16Client-to-Server

This message is not sent from the client.

Server-to-Client

User "x" has entered chat room "y".

integer

16 (Message Code)

string

room

string

username

UserLeftRoom:17Client-to-Server

This message is not sent from the client.

Server-to-Client

User "x" has left chat room "y".

integer

17 (Message Code)

string

room

string

username

ConnectToPeer:18Client-to-Server If we cannot establish a direct connection to a user (for example, they are behind a firewall), we send this message to the server, which will tell the peer to connect back to us.

integer

18 (Message Code)

integer

token

string

username

string

type: "P"/"F" (see PeerInit)

Server-to-Client

If someone cannot establish a connection with us (for instance, we are behind a firewall), the server sends this message to us. We then attempt to establish a direct connection to the peer.

integer

18 (Message Code)

string

username

string

type: "P"/"F" (see PeerInit)

integer

ip address

integer

port

integer

token

MessageUser:22Client-to-Server

Send a private chat message to a user

integer

22 (Message Code)

string

username

string

message

Server-to-Client

Somebody sent us a private chat message

integer

22 (Message Code)

integer

message ID

integer

timestamp

string

username

string

message

MessageAcked:23Client-to-Server

Confirmation of receiving a private chat message. If we do not send it, the server will keep sending the chat phrase to us.

integer

23 (Message Code)

integer

message ID

Server-to-Client

This message is not sent from the server to the client.

FileSearch:26Client-to-Server

We send this to the server when we want to search for something.

integer

26 (Message Code)

integer

token

string

search text

Server-to-Client The server sends this to tell us someone is searching for something.

integer

26 (Message Code)

string

username

integer

token

string

search text

SetStatus:28Client-to-Server

Change my away/online status.

integer

28 (Message Code)

integer

new status, see above

Server-to-Client

This message is not sent from the server to the client. SharedFoldersFiles:35Server-to-Client

We send this to the server to tell it how many files and folders we are sharing.

integer

35 (Message Code)

integer

folder count

integer

file count

Server-to-Client

This message is not sent from the server to the client. GetUserStats:36Client-to-Server This message is not sent from the client to the server.

Server-to-Client

The server sends this message to us to indicate a change in a user's statistics.

integer

36 (Message Code)

string

username

integer

avgspeed

integer

downloadnum

integer

something

integer

files

integer

dirs

QueuedDownloads:40Client-to-Server

It is unknown whether this is valid.

Server-to-Client

The server sends this to indicate if someone has download slots available.

integer

40 (Message Code)

string

username

integer

slotsfull

PlaceInLineResponse:60Client-to-Server

Ask the server what place in line we are ...?

integer

60 (Message Code)

string

username

integer

token (token of original file request?)

integer

place (...?)

Server-to-Client The server sends this to indicate change in place in queue while we're waiting for files from the other peer. integer

60 (Message Code)

string

username

integer

token (token of original file request?)

integer

place

RoomAdded:62Client-to-Server

Unknown if this is valid.

Server-to-Client

The server tells us a new room has been added

integer

62 (Message Code)

string

room name

RoomRemoved:63Client-to-Server

Unknown if this is valid.

Server-to-Client

The server tells us a room has been removed

integer

62 (Message Code)

string

room name

RoomList:64Client-to-Server

Request a list of rooms? integer

64 (Message Code)

Server-to-Client

The server tells us a list of rooms. integer

64 (Message Code)

integer

number of rooms

string

name of room #1

string

name of room #2

:

:

string

name of room #n

integer

user count records

integer

user count in room #1

integer

user count in room #2

:

:

integer

user count in room #n

ExactFileSearch:65Client-to-Server

It is unknown whether this is valid. Normal file search is a symmetric operation (the Client-to-Server and Server-to-Client messages are exactly the same and both valid), which would lead one to believe that maybe the ExactFileSearch works the same way.

Server-to-Client

Someone is searching for a file with an exact name

integer

65 (Message Code)

integer

token

string

filename

string

folder

integer

size

integer

checksum

string

username

AdminMessage:66Client-to-Server

unknown if this is valid

Server-to-Client

The admin is sending a broadcast message. ("The service is going down for maintenance in 10 minutes!")

integer

66 (Message Code)

string

message

GlobalUserList:67Client-to-Server

We send this to get a global list of all users online.

integer

67 (Message Code)

Server-to-Client

The list of users.

integer

67 (Message Code)

See user list format in JoinRoom message

TunneledMessage:68Used to tunnel a message through the server, I would assume...(?)

integer

68 (Message Code)

string

username (to? from? depends on direction?)

integer

code

integer

token

integer

IP address

integer

port

string

message

PrivilegedUsers:69Client-to-Server

Get a list of all users that made a donation

integer

69 (Message Code)

Server-to-Client

The returned list of users

integer

69 (Message Code)

integer

number of users

string

username #1

string

username #2

:

:

string

username #n

AddToPrivileged:91TODO, but likely something only an admin can do. We would assume it takes a username and a duration. CheckPrivileges:92Client-to-Server

How much privileged time do I have left from my donation?

integer

92 (Message Code)

Server-to-Client

You have this many days. integer

69 (Message Code)

integer

number of days(?)

CantConnectToPeer:1001Client-to-Server

We send this to say we cannot connect to a peer after it has asked us to connect.

integer

1001 (Message Code)

integer

token

string

username

Server-to-Client

The server sends this if we asked a peer to connect and it cannot do it. This means a connection cannot be established in either direction--both parties are firewalled.

integer

1001 (Message Code)

integer

token

Relogged?Server sends this if someone else logged in under our nickname then disconnects us.

RemoveUser?Client-to-Server

Used when we no longer want to be kept updated about a user's status. This message is defined in the Python code, but not associated with a message code. Maybe it falls into one of the message code gaps?

integer

??? (Message Code)

string

username to stop watching

CantCreateRoom?Server-to-Client

The server sends this to tell us a new room cannot be created?

Peer MessagesJump directly to a peer message: PeerInit PierceFW GetSharedFileList:4 SharedFileList:5 FileSearchResult:9 UserInfoRequest:15 UserInfoReply:16 FolderContentsRequest:36 FolderContentsResponse:37 TransferRequest:40 TransferResponse:41 PlaceholdUpload:42 QueueUpload:43 PlaceInQueue:44 UploadFailed:46 QueueFailed:50 PlaceInQueueRequest:51

PeerInitThis message is sent by peer that initiated a connection, not necessarily a peer that actually established it. Token apparently can be anything. Type is 'P' if it's anything but filetransfer, 'F' otherwise.

byte

1 (Message Code) Note that this is a BYTE!

string

username

string

type

integer

??? This seems to always be a constant (300 or 0x0000012c)

integer

token

PierceFWClient has asked the server to tell the peer to contact us. The token should be associated with the peer user.

byte

0 (Message Code) Note that this is a BYTE!

integer

token

GetSharedFileList:4Client-to-Peer

The client sends this to a peer to ask for a list of files.

integer

4 (Message Code)

Peer-to-Client

It is unknown whether this is used.

SharedFileList:5Client-to-Peer

It is unknown whether this is used.

Peer-to-Client

A peer responds with this message when sent a GetSharedFileList. This message can be a little complex, considering it contains data from three nested loops: directories, which contain files, which contain attributes. When implementing parsing of this message, it may be helpful to note that within each directory, the list of files (each with its own list of sttributes) is in the exact same format as the list of files returned from FileSearchResult.

integer

5 (Message Code)

The following data is zlib compressed:

integer

Number of directories

string

Directory name #1

integer

Number of files in directory #1

byte?

Dir#1, File#1 code(?)

string

Dir#1, File#1 filename

integer

Dir#1, File#1 size1

integer

Dir#1, File#1 size2

string

Dir#1, File#1 ext

integer

Dir#1, File#1 number of attributes

integer

Dir#1, File#1, Attr#1 type

integer

Dir#1, File#1, Attr#1 value

:

:

integer

Dir#1, File#1, Attr#n value

:

:

:

:

integer

Dir#n, File#n, Attr#n value

FileSearchResult:9Client-to-Peer

It is unknown whether this is used.

Peer-to-Client

This is sent in response to a file search match. Token is taken from original FileSearch message. You will note that the file data is similar to that of SharedFileList, only without the outermost loop (directories). It contains simply a list of files, each with a list of attributes.

integer

9 (Message Code)

The following data is zlib compressed:

string

username

integer

token

integer

Number of files

byte

File #1, code

string

File #1, filename

integer

File #1, size1

integer

File #1, size2

string

File #1, ext

integer

File #1, number of attributes

integer

File #1, Attr #1 type

integer

File #1, Attr #1 value

:

:

integer

File #n, Attr #n value

byte

Free upload slots

integer

Upload speed

integer

In Queue

UserInfoRequest:15Client-to-Peer

integer

15 (Message Code)

Peer-to-Client

It is unknown whether this is used.

UserInfoReply:16Client-to-Peer

It is unknown whether this is used.

Peer-to-Client

integer

16 (Message Code)

string

User's description

byte

Does this user have a pic?

string

This data element is only present if the previous byte is true. This string contains the user pic file content

integer

User uploads

integer

Total uploads

integer

Queue size

integer

Slots available

FolderContentsRequest:36FolderContentsResponse:37TransferRequest:40Client-to-Peer

Ask a peer for a file. See the sequences section at the bottom of this document. Token is [new, unique token? taken from another message?].

integer

40 (Message Code)

integer

Direction constant, see above

integer

Token

string

filename

integer

This data field is only present if direction==1. File size.

Peer-to-Client

Tell a peer we are about to send them a file. (Used when piercing a firewall?) The message format is exactly the same as the client-to-peer version.

TransferResponse:41Client-to-Peer or Peer-to-Client

This is the proper response to a TransferRequest message. "Yes, I agree to take the file" or "no, I do not agree to take the file." Token is taken from TransferRequest message.

integer

41 (Message Code)

integer

Token

byte

Allowed?

If Allowed is true:

integer

Optionally, the file size

If Allowed is false:

string

Optionally, a message explaining why the request was denied

PlaceholdUpload:42Not sure yet.

integer

42 (Message Code)

string

Filename

QueueUpload:43Not sure yet.

integer

43 (Message Code)

string

Filename

PlaceInQueue:44Client-to-Peer

It is unknown whether this is used.

Peer-to-Client

You are in queue position x for file y. This is the response to a PlaceInQueueRequest.

integer

44 (Message Code)

string

filename

integer

place

UploadFailed:46Not sure yet.

integer

46 (Message Code)

string

Filename

QueueFailed:50Not sure yet.

integer

50 (Message Code)

string

Filename

string

Reason

PlaceInQueueRequest:51Client-to-Peer

What place in your queue am I? The response is a PlaceInQueue message.

integer

51 (Message Code)

string

Filename

Peer-to-Client

It is unknown whether this is used.

Message SequencesThis section will attempt to describe the message sequences for common operations.

LoginUser logs in successfully, gets server greeting, gets privileged user list, gets chat room list, starts monitoring buddies client sends Login message client sends SetWaitPort message server sends Login response message server automatically sends a RoomList response server automatically sends a PrivilegedUsers response client sends SharedFoldersFiles message client sends AddUser message for each buddy in buddy list server sends AddUser response for each buddy in the buddy list SearchTODO: User performs a search ChatTODO: User enters a room, listens, speaks, then exits room Obtaining Peer Address, basicThis sequence will grab a peer's address (ip+port), given the username, in the most simple manner. Client sends GetPeerAddress message Server sends GetPeerAddress response Obtaining Peer Address, advancedThis sequence will start monitoring a user (as if that user were on your buddy list), and use that information to not only obtain the address, but get notified if the user goes offline. This is the method that the Python SoulSeek client uses. client sends GetUserStatus message to server server responds with GetUserStatus message with status client sends AddUser message to server server responds with AddUser message server sends unsolicited GetPeerAddress message Note: The following File Transfer scenarios cover every combination and permutation of the three states (client FW, peer FW, queue). They all assume the peer address has been obtained by one of the above methods.

File Transfer, basicClient may or may not be firewalled, peer is not firewalled, peer has no wait queue

client opens a "P" type socket to the peer. This need not be a NEW socket. If a "P" type connection to the peer has already been established (for instance, because the peer has sent you a search result), it can be reused. client sends PeerInit "P" message immediately followed by TransferRequest message peer optionally sends back 12 bytes (the 5th is zero or one)

(Note from Brian: I am a little bit worried about the random 12 bytes that sometimes get sent before a TransferResponse message. The first four bytes are obviously not a message length. Like I said in the comments, the Python code (slskproto.py:SlskProtoThread..process_peer_input()) has some wacky if-elseif-else logic in there that gets called only if it is a non "F" peer connection and it is the first message received.) peer sends back TransferResponse message client opens second socket to peer client sends PeerInit "F" message to peer peer sends file client closes second socket to peer File Transfer, firewallTODO: Client is not firewalled, peer is firewalled, peer has no wait queue File Transfer, two firewallsClient is firewalled, peer is firewalled, wait queue does not matter

A peer-to-peer connection in this situation is impossibleFile Transfer, queue 1TODO: Client is not firewalled, peer is not firewalled, peer has wait queue File Transfer, queue 2TODO: Client is not firewalled, peer is firewalled, peer has wait queue File Transfer, queue 3TODO: Client is firewalled, peer is not firewalled, peer has no wait queue End of Document

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有