wiki:VirtualCommunities

 Visit forum
 Forum search "VirtualCommunities"
 Discuss "VirtualCommunities"

Virtual Communities

status: initial operational code

[ToDo] list DONE:

  • Better friendship invite system: show new incoming & pending requested invites
    In order to send/receive friend's request, there are three possibilities:
    • Phase 1: If one's friend(s) is online, while she is adding her
    • Phase 2: If one's friend(s) is offline, while she is adding her
      (Re-try mechanism)
    • Phase 3: In case, both the parties are offline, then solution would be to save acceptance/rejection of friending at Taste Buddies/Friends?
      (multiple 3rd party buffering)
  • Keep open TCP connection to friends
  • Send instant message to friend
    • Phase 1: both parties are online
    • Phase 2: Use re-try and 3rd party buffering mechanism

For next release Jan/Feb?:

  • Add friend V2 after measurement feedback
  • SocioCast: Peer is now online at IPv4+port
  • Friends news feed; goal of fostering connectedness
    • new file/view
    • new rating
    • added friend
    • changed status message
  • Send private messages

March+

  • CommentCast?: attach comments to each swarm; easy message board by extending PEX within a swarm?
  • Easy import of friends; use easy approach with PermID attachment to Nickname at Server
    Every friend which uses Tribler already has their PermID already visible at their account info
  • Closed group swarms

Technical overview of mutual friendship

Logical Overview

On start FriendsRequestHandler.py is registered as an Overlay Application. Its main purpose is to deal with friending requests, and its response. For peers, who want to add friends (other peers), either by selecting them from Tribler's "people found" section, or explicitly adding by their details in "add a friend" popup, this function friendRequestSend is called.

def friendRequestSend (self, parent, utility, editfriend = None):
        """ Called when user adds someone from the person found, or by explicitly adding someone with her credentials
        It establishes overlay connection with the target peer """
        #Connection with the target peer is established, with mentioning of call back function
        self.overlay_bridge.connect(editfriend['permid'], self.friendRequestConnectionEstablishmentCallBack)

For receiving acknowledgment of the connect routine, this function tries to re-connect if an exception arises. On successful connect, it tries to send a friending request to the target peer. The message contains requestee's details, like Nick, IP, Port and Permid.

def friendRequestConnectionEstablishmentCallBack(self, exc, dns, target_permid, selversion):
        """ Callback function for the overlay connect function, i.e., friendRequestSendWithOnlyID and
        friendRequestSend """
         
        if exc is not None:
            #Send connection request every five minutes
            self.overlay_bridge.add_task(lambda: self.friendRequestSendWithOnlyID(target_permid), 300)
        # send the message if there was no pending messages; This message contains peer's own information, i.e, nickname, ip and permid
        if self.lastSentMessage is None:
            msg = ':Hi:'    
            text = msg+str(self.mynickname)+':'+str(self.myip)+':'+str(self.myport)+':'+show_permid(self.mypermid)
        #In case of exception, save this message
            self.lastSentMessage = FRIENDREQUEST + text
            self.overlay_bridge.send(target_permid, FRIENDREQUEST + text, self.friendRequestConnectionEstablishedCallBack)
        # To see if the last message was successfully sent or not; if not, re-try
        else:
            self.overlay_bridge.send(target_permid, FRIENDREQUEST + self.lastSentMessage, self.friendRequestConnectionEstablishedCallBack)
        def friendRequestConnectionEstablishedCallBack(self, exc, peer_permid, other=0):
        # If an exception arises
        if exc is not None:
            #Send connection request every five minutes
            self.overlay_bridge.add_task(lambda: self.friendRequestSendWithOnlyID(peer_permid), 300)
        else:
            self.lastSentMessage = None # On successful connect, make lastMessage as none

For receiving overlay messages, overlay message handler has to be created and registered. The same class FriendsRequestHandler.py is responsible for it.

HandleMessage? is called by the OverlayThreadingBridge on receiving a message for a particular protocol. In this case, it is FRIENDREQUEST protocol. This function does two main things -- Display a popup message to a peer to accept/reject a friending request -- This response is received by the requestee, and then based on the response, either friend is "approved", or deleted from the friends' list

Peers are notified by a pop-up whether their friending request has been approved, or not.

    def handleMessage(self,permid,selversion,message):
        ''' This is called by the OverlayThreadingBridge to receive incoming messages, which were sent by
        Overlay Bridge'''
        pdb = PeerDBHandler.getInstance() # instance of peer db
        fdb = FriendDBHandler.getInstance() # instance of friend db
        temp = message.split(':') # split the message into array of string; separated by ':'
        isFriend = fdb.isFriend(permid) # to see that the following peer is already a friend, or not
        #variable to store peer's response on friending request
        approved = ''
        # Hi being the first element shows that friending request is being received
        if temp[1] == 'Hi':
            # See the database if it contains any information of this peer
            if pdb.hasPeer(permid):
                if not isFriend: # And if that peer is not already added as a friend, either approved, or unapproved
                    dial = wx.MessageDialog(None, 'DB YES: Do you want to add 
'  + temp[2]+ '
 as you friend?  ', 'Question', 
                                        wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
                    returnValue = dial.ShowModal()
                    approved = ":NO:" 
                    if returnValue == wx.ID_YES:
                        approved = ":YES:"
                        pdb.updatePeer(permid, commit=True, friend = 2)
                    elif returnValue == wx.ID_NO:
                        pdb.deletePeer(permid)
                else: # In case, requestee is already added as friend, just make this requestee as an approved friend
                    pdb.updatePeer(permid, commit=True, friend = 2)
                    approved = ":YES:" 
            # Now this peer had to be locally saved as well, since database doesn't have any record of it
            else:
                # Dialogue for asking wheter to approve, or deny the request
                dial = wx.MessageDialog(None, 'DB NO: Do you want to add 
'  + temp[2]+ '
 as you friend?  ', 'Question', 
                                        wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
                returnValue = dial.ShowModal()
                approved = ":NO:"  # By default, set the value to 'No' to friending request
                # In case of acceptance, save 'YES'
                if returnValue == wx.ID_YES:
                    approved = ":YES:"
                    # text = msg+str(self.mynickname)+':'+str(self.myip)+':'+str(self.myport)+':'+show_permid(self.mypermid)
                    friend = {'ip':temp[3], 'port':temp[4], 'name':temp[2]}
                    # Add that peer into the database
                    pdb.addPeer(permid, friend)
                    # Update its status to an approved friend
                    pdb.updatePeer(permid, commit=True, friend = 2)
                elif returnValue == wx.ID_NO:
                    # Do nothing when denying a request to the database
                    print "Do nothing"
            # Save the last message, i.e., approved to lastSentMessage, so that in case of error, this message
            # could be resend
            self.lastSentMessage = approved
            # send the peer's response to the requestee 
            self.overlay_bridge.send(permid, FRIENDREQUEST + approved, self.friendRequestConnectionEstablishedCallBack)
        # On receiving response from a peer of friending request    
        elif temp[1] == 'YES' or temp[1] == 'NO':
            approved = temp[1]
            if approved == "YES":
                # update this friend's status in the database as "confirmed friend", or "approved friend"
                dial = wx.MessageDialog(None, 'Hurray! Your request to add has been approved ', 'Information', 
                                   wx.OK | wx.ICON_INFORMATION)
                dial.ShowModal() 
                # Now the status of Friend from 1 to 2 has to be changed, i.e., approved friend
                pdb.updatePeer(permid, commit=True, friend = 2)
            else:
                dial = wx.MessageDialog(None, 'Sorry, your request to add has been denied :( ', 'Information', 
                                   wx.OK | wx.ICON_INFORMATION)
                dial.ShowModal()
                #Remove this peer as a friend, and then update the database
                pdb.updatePeer(permid, commit=True, friend = 0)
        if DEBUG:
            print >> sys.stderr,"FRIENDREQUEST : Got FRIEND REQUEST",len(message)
        else:
            if DEBUG:
                print >> sys.stderr,"FRIENDREQUEST: UNKNOWN REQUEST MESSAGE", ord(t)
            return False

Database Overview
In the database, Friend field of the Peer table is 3 valued now.

  • 0 being not friend
  • 1 being unapproved friend
  • 2 being approved friend

GUI Overview

Also, now the "Friends" section contains another column "Approved/Unapproved? friend"; more specifically, in the FriendsItemPanel.py, a new column "Is approved friend" is added. Now, the reason is why it's added, actually, all friends are added right away, but only those become "approved" ones which are mutually agreed by the target peers. Here is the code snippet of that column

        # Add friend's status
        self.friendstatus = wx.StaticText(self,-1,"",wx.Point(0,0),wx.Size(130,12), wx.ALIGN_RIGHT | wx.ST_NO_AUTORESIZE )        
        self.friendstatus.SetBackgroundColour(wx.WHITE)
        self.friendstatus.SetFont(wx.Font(FS_STATUS,FONTFAMILY,FONTWEIGHT,wx.NORMAL,False,FONTFACE))
        self.friendstatus.SetForegroundColour(self.triblerGrey)        
        self.friendstatus.SetMinSize((165,12))
        self.friendstatus.SetLabel("")
        self.friendstatus.value = None 
        self.hSizer.Add(self.friendstatus,0,wx.TOP|wx.EXPAND,4)

For visual feedback, apart from setting this column for each peer, each approved friend looks different toopltip wise as well.

            # To show that the current friend hasn't approved friending request
            if friendStatusValue == 1:
                self.friendstatus.SetLabel('unapproved')
                self.friendstatus.SetToolTipString('Friending request has not been approved')
                self.friendstatus.value = 1
            # To show that the current friend has approved friending request
            elif friendStatusValue == 2:
                self.friendstatus.SetLabel('approved')
                self.friendstatus.SetToolTipString('Friending request has been approved')
                self.friendstatus.value = 2

Also, the colour of the row is different for approved friends

      # For approved friends, make this row as light grey
      elif self.friendstatus.value == 2:
                colour = wx.LIGHT_GREY

Future Ideas

  • internal use at Amnesty?
  • exchange of video material/files in general- group message exchange/boards
  • Community management
    • group management architecture
    • group leaders
    • white list?
    • membership list discovery/management
    • inject/download/delete rights
  • users always online?

Web resources

Related work

 Scholar link
 P2P links..
 Social Network link

Related literature

Social peer-to-peer for social people
Borch, N.
05: The Int’l Conf. on Internet Technologies and Applications

Social Networks in Peer-to-Peer Systems link
Upadrashta, Y. and Vassileva, J. and Grassmann, W.
05: System Sciences, 2005. HICSS'05. Proceedings of the 38th Annual Hawaii International Conference on

The EigenTrust Algorithm for Reputation Management in P2P Networks link
Kamvar, S.D. and Schlosser, M.T. and Garcia-Molina, H.
Proceedings of the 12th international conference on World Wide Web
03: ACM Press New York, NY, USA

The Dangers of Poorly Connected Peers in Structured P2P Networks and a Solution Based on Incentives
Hartmann, B.O. and Bohm, K. and Khachatryan, A. and Schosser, S.
07: Web Intelligence, IEEE/WIC/ACM International Conference

Evaluating similarity measures: a large-scale study in the orkut social network
Spertus, E. and Sahami, M. and Buyukkokten, O.
05: Conference on Knowledge Discovery in Data, ACM Press New York, NY, USA

Social Peer-to-Peer for Resource Discovery
Liu, L. and Antonopoulos, N. and Mackin, S.
07: Parallel, Distributed and Network-Based Processing, 2007. PDP'07. 15th EUROMICRO

Limited reputation sharing in P2P systems
Marti, S. and Garcia-Molina, H.
04: Proceedings of the 5th ACM conference on Electronic commerce, ACM Press New York, NY, USA

Foreseer: a novel, locality-aware peer-to-peer system architecture for keyword searches
Cai, H. and Wang, J.
04: Proceedings of the 5th ACM/IFIP/USENIX international conference on Middleware, Springer

Ostra: Leveraging trust to thwart unwanted communication
Cai, H. and Wang, J.
04: Proceedings of the 5th ACM/IFIP/USENIX international conference on Middleware, Springer

An internet-deployed epidemic protocol stack
J.A. Pouwelse, J. Yang, M. Meuploder, D.H.J. Epema, H.J. Sips

Attachments