troublesum's Forum Posts

  • - In the expression section there is a Table.AsJSON method that returns the entire object as a JSON string.

  • - In the expression section there is a Storage.AsJSON method that returns the entire object as a JSON string.

  • I think that could be better accomplished using the random or choose functions available in C2. Not sure it would benefit much to add a "pick random" function to the table.

    Here's an example of what I would do to pick a random key value

  • haha... the one about protoType being "pants on head stupid" was priceless... I cringe every time I have to work on someone else's code that uses it.

  • Tom - Just a thought... but to at least mitigate the spamming currently going on, maybe a time restriction on the frequency of posts for users. Like a user can't make new posts more than once per 5-10 min or something like that. Make it both IP and username restricted to catch multiple usernames from the same IP. I doubt any user needs to post a question more often than that and would at least stop the flooding. Any way. good luck and keep up the fight

  • Ashley - Yah I wrote my own WebRTC client for a completely different web application (I will probably extend it to a C2 plugin for myself in the near future) and this was something I came across during its development. It was rare but often enough I decided to code around it.

    What I found was that in rare cases after the host has created the offer it can start sending ICE candidates almost immediately. I would have assumed the peer would have enough time between receiving the offer and generating the answer before receiving the ICE candidates but this wasn't always case. From what I can tell the offer is always received before the ICE candidates since the websocket connection to the signal server is ordered but if sometimes they are received close enough together and they don't give the peer enough time to set a remote description and generate an answer this race condition occurs. Because the peer process of setting the remote description and generating an answer is asynchronous javascript isnt held up and can receive and add an ICE candidate during this time at which point you will get that error as it attempted to add the ICE candidate before completing the answer process. So its an actual race condition that occurs as a result of the trickle ICE implementation in the WebRTC protocol.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Ashley - You didn't respond to my post but I wanted to show you that I can reproduce this error consistently and it might be responsible for some of the connectivity issues your users are having.

    Setup:

    Host Client: Firefox

    Peer Client: Chrome

    Add a delay to the peer so that the peer will receive and add ICE candidates before it creates and answer for the host. This occurs very sporadically on its own but by adding the delay to simulate it you will generate the error every time.

    Effect:

    When Firefox is the host and Chrome is the peer, if Chrome receives an ICE candidate and attempts to add it before generating an answer to the host offer, the connection process stalls and fails. The ICE error will still happen when its Chrome to Chrome and will show in the error console, but the connection process doesn't stall and it still works so its specifically a cross browser compatibility issue on how each handles this event when it happens.

    Here's a screen shot of the error console when i simulate this from my WebRTC setup

    I fixed this by allowing the ICE candidates to trickle in as normal but I queue them up until after the remoteDescritption has been completely setup and then trigger them to be added and allow any others that are still trickling in to be added immediately. Yes it adds maybe a second or two to the setup time but for increased stability it was worth it. I hope this was helpful for you to see what I was trying to explain and that you decide to patch this for your users.

    Thank you

  • Ashley - I would however like to ask your thoughts on what I think I found is a bug (race condition) in the WebRTC signalling process that fails to establish a connection when a race condition occurs where ICE candidates are received and data channels are attempted to be opened before the RemoteDescription is completed on both ends.

    I wrote my own WebRTC module and signalling server i use for a website that sets up a chat rooms and lobby's (eventually will be used for my games ) and I noticed a what i think is flaw in the signalling process (not yours.. but the actual implementation). In some cases the peer|host will send ICE candidates to each other before the offer|answer process is complete. This causes the host to attempt to open the data channels before com is ready. Its rare but I noticed it happen when JavaScript was running slow on one machine (cursor freezes for a sec while the CPU is doing something) and watching the debug console as ICE candidates were recieved before the offer|answer process was complete and the connection process stalls and fails.

    I over came this by adding one more step where I store all ICE candidates received on both host and peer side and then after the host has received an answer from the peer and completed the RemoteDescription process the host then sends an "answer-accepted" message to the peer through the signal server at which point both host and peer now add the ICE candidates they stored from each other and allow future ICE candidates to be added right away. Once ICE candidates are added, that's when the host attempts to open the data channels between himself and the peer. By forcing this process to be last I get 100% connect rate now where as before it would fail some times. For me this made a difference in improving stable connection setup between slower and faster computers and is something I think you may want to look into.

  • xanxion - While I agree that people shouldn't have to open ports to play multiplayer games its not uncommon for games to have support documentation stating that ports may need to be open for proper usage if you're router is blocking them (rare but it happens).

    The WebRTC implementation is actually a thing of beauty from a developer stand point. Because most (more like all) routers will block "anonymous" internet requests from unknown ip:ports making it impossible for two browsers (or two of anything for that matter) to connect to each other with out each specifically sending a request on that same port. (servers are different because those ports are open as they are expecting anonymous requests)... but web pages work the same way... my server couldn't just send you webpage you didn't request. Your router will block the anonymous port 80 message I'm sending you from my ip because you didn't originate the request on your machine for that port. When you type an address in the browser and click enter you send a request out on port 80 (usually) thus notifying your browser that you're allowing a response on that port from the ip i sent the request to.

    I'm generalizing this but the devs at google found a back door to this security process by spoofing requests from each computer (browser) to each other thus causing your router to see that YOU sent a request to some guys computer on a specific port and even though he blocked your request he attempts to do the same thus opening both routers to each end to internet traffic from each other so long as its on the same port they both sent the spoofed request on. To set all this up, first both computers need to get some sync info (ip of the peer and port to use) which is where the signalling server comes in to coordinate this transaction to get both routers on each end to allow communication between pair and setup the data channels. After which a websocket is opened between the two so the connection stays open (web page request close the connection after receiving data back from the server).

    So any way try not to talk so negatively about something that is extremely complicated and really is a masterpiece of network communication that for all intent a purpose is still relatively beta as google/firefox/IE and others are still working and developing WebRTC standards.

  • There are 2 common ways to send data to your php server from a webpage and both in essence are the exact same process.

    1) POST - Request: This is most common for form submission (IE.. username, and password text boxes that submit those variables to a url). The variables are sent behind the scenes somewhat protected from general view. The user is taken to mydomain.com but the data you sent was passed in the request headers and not out in the open for the user to see.

    Pros: data is hidden from plain view and more secure

    2) GET - Request: This is most common for page drawing and not for sending sensitive information and passed in url param string (ei.. mydomain.com?version=1)

    This sends a request to url just like the post does but the data you are passing is not hidden behind the scenes and is out in the open attached to the end of the url for the user to see.

    Pros: when the page loads that param is still at the top so all future ajax request from that domain will also have this param attached to it

    Both of these methods however require the browser to reload a url or goto a new one to pass this data to the server. Sometimes you may just want to send data but not have to reload the entire page for the user. This is where AJAX comes in. Ajax can do either of those by faking a form submission or url request and then returning what ever the server echo'ed back.

    PHP sees an AJAX request no different than a form submission or url page request. its all the same. PHP gives you 3 global arrays for accessing

    $_POST - this global var will contain any variables sent from a for submisison

    $_GET - this global var will contain any variables that were sent in the url string

    $_REQUEST this gets both. i don't see many people use this but its my favorite as i can use it for testing (putting params in the url) orproduction (actually POST'ing them)

    And as you would expect the AJAX plugin in C2 supports both ..in truth it really doesn't matter which you choose since AJAX is hidden anyway (keep in mind you can press f12 on any browser and see it in the network traffic so no its not's completely hidden its just out of plain view of the user)

    now when you are posting variables to PHP that will end up in a SQL command you need to protect your SQL database from injection. Imagine you have a SQL command like this

    $username = $_REQUEST['username']

    "SELECT * FROM users WHERE username='$username';"

    if you think about it for a sec if some guy that understands SQL could instead of typing "troublesum" in the username text box you provided they type "troublesum'; DROP TABLES" . SQL will execute the two querys both selecting the user and the DROPPING ALL YOUR TABLES. You need to protect against and make sure SQL treats the entire $username var as a string and not allow additional commands. thats where mysqli_real_escape_string(). This will add slashes to those dangerous chars ; ' that allow them to hijack your command and wil see the whole thing as one long username which of course SQL wont find because the username "troublesum'; DROP TABLES" doesnt exist.

    I think that about covers POST GET SQL 101 for today. good luck

  • - ah.. easy enough.. I just added it and updated the plugin.. if you re-download the plugin and the example capx again you will see at the bottom how to sort a list by fields instead of values.. the action is called "sort list by field".

  • - Hi and thank you ...you're right i must have forgotten to add it to the text capx. sorry about that.. i use it in my project so i know feature works but i just in case tested it anyway and add it to the example. You will find it at the bottom now if you wish to re-download the test capx for reference.

    ands here's screenshot of the example on how to sort

    let me know if you find anything else i missed or if you have any questions.. thank you

  • mdvgames - unfortunately i don't... The example I provided in this thread needs work to enable the ability for peers to call functions on specific peers instead of just being able to call them on all peers all the time. (and the process is complicated enough as it is) it was just a proof of concept i created but lead me to work on my plugin instead. You will need to hack it to correct for any imbalances. (Ie if peerid already exists dont re-respawn it.)

    I would release my plugin that simplifies the whole thing but i'm not supporting it as it hooks into official (multiplayer & function) plugins maintained by Ashley and as he makes changes to them could break mine and would leave your project broken unless i correct for any changes he might make which i don't want to be responsible for. .. If you message me ill provide you a link to download it for personal use but to use at your own risk that someday it could be broken and I might not be around to fix it.

  • ah.. i see what your saying. I haven't looked at this in a while and didn't see that bug. Yah the problem is when the peer asks the host to send him all other peers, the host calls the "spawn_Player" function for everyone and not just the peer that requested it. I forgot about that problem and was why I stopped using this .. Trying to coordinate functions to "specific" peers was too complicated in the event sheet so i created a personal plugin that wraps the multiplayer and function plugins together so it does it all for me in a single call. On the example capx however you can just add a check to the "spawn_Player" function that if an object with that peerid already exists to ignore its creation.

  • azrail13 - have you tried just displaying the the AJAX.lastdata in a text object to see what your getting back. After looking at your login.php I can see a few errors that might come up. You say this worked when it was in testing but I can't see how. you might be getting a SQL error and not even know it becuase you are storing the result in an (int) variable so the string is just getting converted to a 0 (int zero)

    Maybe SQL has gotten better at adapting to syntax usage but his looks like it shouldn't work?

    $qz = "SELECT id FROM members where username='" . $username . "' and password='" . $password . "'";
    $qz = str_replace("\'", "", $qz);
    $result = mysqli_query($con, $qz);
    [/code:1joqfaoj]
    
    You are stripping single quotes from the query string before executing it but that means you are comparing columns (username & password) to non string values which SQL will interpret as other columns and throw an error because they don't exist
    
    Example 
    "WHERE username=player1 &password=test" will throw an error becuase SQL will think the values "player1" and "test" are columns  since they are not in single quotes
    
    It should be "WHERE username='player1' &password='test'" (The single quotes allow SQL to know you compairing the column value to a string value and not another column or equation
    
    And while this might work it is extremely unstable way of getting the data. On the off chance more than row is returned this will break and what if the username and password don't find a match? 
    [code:1joqfaoj]
    while ($row = mysqli_fetch_array($result)) {
        echo $row['id'];
    }
    [/code:1joqfaoj]
    
    Try using this
    [code:1joqfaoj]
    
    //make sure param is there and catch it if not so PHP doesn't throw a Notice error
    $username = isset($_GET['fname']) ? $_GET['fname'] : '';
    $password = isset($_GET['fpass']) ? $_GET['fpass'] : '';
    
    //Validate you received the params you expected
    if($username=='' || $password==''){
        echo 'Invalid login';
        exit; //make sure no other code is executed beyond this error;
    }
    
    //protect from SQL injection
    $username =  mysqli_real_escape_string($con,$username); 
    $password =  mysqli_real_escape_string($con,$password);
    
    //You need the single quotes around the values or SQL will break
    $qz = "SELECT id FROM members where username='" . $username . "' and password='" . $password . "'";
    $result = mysqli_query($con, $qz);
    
    //There should only be 1 row returned. No need for a while statement
    $row = mysqli_fetch_array($result);
    
    //The $row may be null if it was invalid username and password combo
    if(!$row){
        echo 'Invalid login';
        exit; //make sure no other code is executed beyond this error;
    }
    echo $row['id']
    [/code:1joqfaoj]
    
    Lastly keep in mind that $row['id'] will be returned as a string (all echo statements doesnt matter what they are are returned in string type as literal text) 
    
    so first in C2 you need to compare against the possible error and catch it
    Condition (AJAX.LastData=='')  - Ajax was empty and something went wrong. stop code
    Condition (AJAX.LastData=='Invalid login') - Ajax returned a notice of invalid login and you need notify the user so they can try again 
    
    Then if that passes you need to store it in userid but convert the (string) you received from php to (int) so it is casted correctly to the userid variable
    Action userid = int(AJAX.LastData)