Tuesday, November 23, 2010

Net Neutrality Summary

     The following is a summary of a presentation I'm to give on the Tuesday of next week.  Lemme know what you think -- whether or not it hits all the points of interest on the topic, if the organization is well structured, etc.  Do note that this is merely a summary, not a full on paper, so use of abbreviations and conversational inconsistency of person shouldn't be of particular concern.

Daniel Tanner
November 23rd, 2010
CMPT 335
Net Neutrality Presentation

     My security presentation covers the topic of Net Neutrality.  It is relevant to our class in security because it has to do with the availability and integrity of internet services.  Definition of the term "Network Neutrality" itself is as good a place as any to begin.  I should like to follow up with a consideration of various bills that have been introduced or passed in congress relating to the issue, leading into a discussion of the current one on the table.  Naturally this will lead into consideration of the current policies in place at the Federal Communications Commission and some cases which have come up.  Since the presentation up to said point will mostly engender the 'for' or 'pro' side of the issue, it seems only fair to round it out by discussing some of the concerns of parties opposed to the bill.
     "Net Neutrality" is rather difficult to pin down to one specific definition, since the definition used in legislative bills on the subject use one definition, internet service providers and network administrators use another, and the popular media uses still another.  The current policy of the Federal Communication Commission is often described as one of network neutrality, where all content is treated equally and there is no prioritization.  To put that into more specific terminology, it would seem to mean that no packet prioritization is in play (routers act as a 'dumb' network where the actual content of packet doesn't come into consideration).  This is not quite how the network works in reality (for example, compare UDP and TCP/IP protocols and how TCP is built to scale itself back when traffic gets heavy, while UDP does not.  This effectively gives any content using UDP priority over TCP traffic).  This is where another definition of network neutrality comes into play; that it is a policy of equal treatment in regard to users using certain services.  Providers are prohibited from blocking or throttling any 'lawful' services and/or any 'lawful' content (where lawful is generally taken to refer to trafficking of certain content like child pornography being illegalized).
     A number of bills have come and gone through congress in an effort to pass more regulations concerning network traffic control.  The first of these bills comes from around 2005, under the name of the Internet Freedom and Nondiscrimination Act.  When that failed, congress attempted to include most of the basic legislation as a rider on the COPE Act, though this was also shot down.  It was again brought to the floor as the Net Neutrality Bill.   This one also failed to pass, and the modern incarnation which is currently in committee hearings is called the Internet Freedom Preservation Act.  I've included the summary of the bill as part of the presentation and intend to read the main points of the policy, but it essentially prohibits ISPs from:  preventing any particular individual from using internet access services, imposing special charges on particular types of content providers, preventing the usage of any 'lawful' device in conjunction with said services, establishing a scheme for prioritizing any given host's traffic over other hosts, and/or installing any network functionality to enable any of the aforementioned activities.  It also sets the FCC up as the agency in charge of enforcing said regulations.
     The current policy of the FCC isn't actually all that different than the proposed bill, though the regulations tend towards the vague and nebulous.  Basically the policy is that all users should have access to lawful content, be able to run lawful applications/services, use lawful devices, and the FCC is directed to promote competition among iSPs and various content providers.  A few incidents have arisen where these various powers have been tested.  Whether it has proven enough, too much, or too little has been a primary point of contention among the various parties who have thrown their hats into the socio-political arena of ideas concerning this topic.
     Comcast has become perhaps the most (in)famous ISP because of a related incident.  In October 2007, the company, primarily in an effort to cooperate and comply with RIAA, MPAA, and federal rulings on copyright infringement, decided to block and/or interfere with network traffic assumed to contain pirated music and movies transferred over Bittorrent and other peer-to-peer filesharing software.  The method of blocking was rather indirect (a DoS attack using reset packets), but due to the fact that a number of customers had legitimate services hindered or blocked by this incident, Comcast was brought to court by both a class action civil suit and a criminal charge from the FCC.  While the criminal charge was not successful (apparently still active in appeals, though), Comcast was charged $16 per share to settle the civil suit.  I'll go into more detail on the other events in class, since this summary is already getting long (admittedly, this is the best-documented one).
     Let's finish out with the arguments against.  The primary argument is not so much against the idea of Net Neutrality per se, as it is that the system already in place gets the job done.  More specifically, the market as it is prevents ISPs from enacting the kind of priority systems previously mentioned; partly because the changing of the hardware is either technically infeasible (too expensive if even possible) or would end up cutting that particular ISP off from the rest of the internet, which is hardly the kind of service customers would want or pay for.  Another argument against is the consideration of ISPs as the owners of these various communications networks, which they have paid to implement.  Several property, which is, as ever, the central right, would seem to dictate that ISPs ought to have complete control over their own networks and their use (much as wireless communications companies have over their networks); and that any regulations to enforce government control would be unconstitutional.  The next argument of note is the consideration of innovation in the network core -- that different methods of network management would be more difficult to attempt, or ISPs would be less likely to try in a more regulated environment.  More technically inclined individuals provide yet another argument (and this goes back to the original way in which net neutrality is defined) -- that not all services are equal, and for the network to operate efficiently, different services must necessarily be treated differently.  That should cover most, if not all, of the views in both directions.

     Sources used in gathering the information in this summary and for the presentation are as follows (using Chicago Style Citations):

1  Lessig, Lawrence.  “No Tolls on the Internet.”  The Washington Post.  Posted June 8th, 2006.  Accessed November 23rd, 2010.  http://www.washingtonpost.com/wp-dyn/content/article/2006/06/07/AR2006060702108.html .
2  Wu, Tim.  “Network Neutrality FAQ.”  Posted December 26th, 2008.  Accessed November 23rd, 2010. http://timwu.org/network_neutrality.html .
3  Markey, Edward (Sponsor D-MA) et al.  H.R. 3458 – Internet Freedom Preservation Act of 2009. http://www.opencongress.org/bill/111-h3458 .
4  Carter, Nick.  “What is Network Neutrality?”  Accel Networks:  Fixed Wireless Broadband Blog.  Posted August 10, 2010.  Accessed November 23rd, 2010. http://www.accel-networks.com/blog/index.php?q=/2010/08/what-is-net-neutrality.html .
5  Google et al.  Open letter to Congress concerning Net Neutrality policy.  Dated March 1, 2006.  Accessed November 23rd, 2010. http://www.publicknowledge.org/pdf/nn-letter-20060301.pdf .
6  Dortch, Marlene H.  Policy Statement.  Federal Communications Commission.  Dated September 23rd, 2005.  Accessed November 23rd, 2010. http://hraunfoss.fcc.gov/edocs_public/attachmatch/FCC-05-151A1.pdf
7  “Net Neutrality.”  Wikipedia.  Last modified November 10th, 2010.  Accessed November 23rd, 2010. http://en.wikipedia.org/wiki/Net_neutrality
8  Hart, Jonathan D. (2007). Internet Law. BNA Books. p. 750.  (Referenced in 7).
9.  Andrews, Tim.  “Does ‘Net Neutrality’ Violate the First Amendment?”  Americans for Tax Reform.  Posted November 11th, 2009.  Accessed November 23rd, 2010. http://www.atr.org/net-neutrality-violate-first-amendment-a4189
10.  Majoras, Deborah et al.  “Broadband Competition Policy.”  FTC Staff Report June 2007.  Accessed November 23rd, 2010. http://www.ftc.gov/reports/broadband/v070000report.pdf
11.  Solomon, David H. et al.  “In the Matter of Madison River Communications, LLC. And Affiliated Companies.”  Federal Communications Commission.  Accessed November 23rd. http://hraunfoss.fcc.gov/edocs_public/attachmatch/DA-05-543A2.pdf

Monday, November 15, 2010

An n^n algorithm (or a surefire way to freeze up your memory lickety-split)

     So one of my friends and I were talking about algorithm analysis and tried to think up a quick and dirty n^n algorithm (that is, one which grows on a more than factorial order) and this is what we came up with.  Be forewarned:  Calling this function with an argument of more than 30 is likely to eat all your memory (on the school computer we tried it on we got a BSOD.  Wheeeeee!)

void int sum(int n)
{
      //base case
      if(n == 0)
          return 1;

      int sum = 0;
      for(int i = 0; i < n; i++)
           sum += sum(i);
      return sum;
}

This is like the fibonacci series on crack (in terms of the call hierarchy), though it ends up falling into a pattern of simply doubling.  You get a slightly more interesting pattern by switching the initialization of sum from 0 to n, but the main point here is to maximize the number of operations in as little code as possible without generating an infinite loop.

Monday, November 1, 2010

Voting Machine Security (CMPT 335 Assignment 9)


Security in the Ballot Box - Issues with Electronic Voting Machines (Part A & B)
            For this assignment I decided to look into the recent allegations of voting machine malfunctions in Las Vegas.  I would like to begin by giving a brief summary of events according to local newspapers and accounts.  I should like to follow up with some information about the particular voting machine used and any relevant security concerns having to do with the specific machine.  This essay will end on my thoughts on the issue -- whether it is being handled effectively, whether it will affect the upcoming election, and so on.
            According to some early voters in Boulder City, Nevada, before getting a chance to cast their ballots the voting machines already had Democrat Harry Reid’s name selected.  It’s not clear if this was already selected as a default (and could be changed) or whether the printed paper ballot would force a vote for Mr. Reid.  Election officials claim that their poll workers have heard no complaints on the matter.  Furthermore Mr. Lemox (the Registrar) claims such malfunctions are impossible, given the technology being used.
            While the model of voting machine went unmentioned in the mass media articles, according to an article on truthout.com the model in question is the Sequioa AVC Edge, which is apparently secure enough to emulate pac-man on – without removing the tamper-evident seals, even.  Now, whether Sequoia has updated their model to be more secure now (and whether truthout’s information on which model is being used is credible) I do not know.  But, the information taken at face value certainly fails to inspire confidence in the security of Nevada voting.  Furthermore, the New Jersey’s Center for Information Age Technology ran a number of tests on this particular model, and while functionality passed most of the criteria given by the State Attorney General, there are some interesting exceptions mentioned.  Specifically of note is that the machine’s paper ballot printer needs to be refilled about once every 120 voters, it doesn’t keep a log of when the paper is refilled, and during a refill, the stored paper ballots are accessible and subject to tampering.  All of this leads to a number of conclusions, few of them reassuring.
            While the machines have no apparent defect in and of themselves, it seems like they are relatively easily hacked into and reprogrammed.  Even regular maintenance allows stored votes to be at risk.  Given that, it is not hard to believe it possible that the allegations made about machines set up to cast votes for the Democrat by default may be true.  And, if these are indeed the voting systems in use, it seems Mr. Lemox and other state officials seem to have jumped the gun a bit in declaring these machines inviolable.
References:
German, Jeff.  “Audit Resolves Voting Irregularity Questions.”  Las Vegas Review-Journal.  Oct. 28, 2010.  Accessed Oct. 30th, 2010.   http://www.lvrj.com/news/audit-resolves-questions-of-irregularities-105990348.html .

“County Denies Voting Machine Malfunction Claims” Fox 5 News, Las Vegas.  Oct. 26, 2010.  Accessed Oct. 30th, 2010
http://www.fox5vegas.com/news/25524494/detail.html .

Friedman, Brad.  “Hacking Harry Reid (or Sharron’s Angle).”  Oct. 26, 2010.  Accessed Oct. 30th, 2010.  http://www.truth-out.org/hacking-harry-reid-or-sharrons-angle64548
Feldman, Ariel J and J. Alex Halderman.  “PAC-MAN on the Sequoia AVC-Edge DRE voting machine.”  http://www.cse.umich.edu/~jhalderm/pacman/

“Report to the Office of the Attorney General:  Sequoia AVC Edge Voter-verified Paper Record System Assessment.”  New Jersey Institute of Technology Center for Information Age Technology.  July 2007.  Accessed Oct. 30th, 2010.   http://nj.gov/state/elections/Hearing-Reports-7.07/NJIT-Edge-report-7.07.pdf
(B) Impressions on technology in voting
            As long as I can remember, I have read articles and watched television news around election time, detailing stories of voter fraud or election fraud of one type or another.  So, I would like to detail a few recurring threads that always seem to come to the fore around voting time (well, my personal experiences and impressions anyway) and discuss whether or not technology has improved these things.
            First of all, I would like to point out that doubts and worries over the accuracy of ballot counts long predate their automation.  Whether you are reading Horace Greeley’s accounts about the corrupt Democrat machine in the 1800s, or about voter intimidation in the South during and after the Jim Crow era (where the Klu Klux Klan tried to force everyone to vote Democrat)... such concerns are hardly limited to the computer era.  In more recent history, the Helping Americans Vote Act of 2002 essentially budgeted something in the neighborhood of $2 billion of federal funds to improve many counties’ electoral systems.  This lead to the widespread use of electronic voting machines, digitized voter registration databases, and was aimed at preventing a repeat of the 2000 presidential election in Florida (where so-called ‘butterfly ballots’ supposedly led to voter confusion and a long cycle of recounts were finally put to an end by a Supreme Court decision).  Did this harm or help the accuracy of our voting system?
            The cynical side of me wants to say it ultimately accomplished nothing.  Whether it’s the aforementioned issues in Las Vegas, or the odiously suspicious election of Al Franken in Minnesota a year or two ago, it all comes down to how much we trust the poll workers to honestly and competently count the ballots at the end of the day.  It’s ultimately the same question whether we’re asking them to manually count those votes, or to provide physical security to prevent the hacking of voter machines.  On the bright side, it has made the poll workers life easier, in that the counting is automated, now.  And for the voter, a touch screen is easy to use, and certainly less annoying than butterfly ballots.  Though, in turn, voting machines are more expensive to buy and maintain than, say, marking down your vote with pen and paper.  And, if environmentalism is your fetish of choice, the requirement of printing out each ballot for extra verification means you’re not really saving on paper.  So, all in all, I have to say the computerization of voting has made things easier in some ways, but also more expensive and just as subject to suspicion.

Thursday, September 23, 2010

GNU Protection Guard Public Key

Just in case you ever wanted to send me coded messages via RSA encryption, the following is my public key:

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.10 (MingW32)

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
=yUP0
-----END PGP PUBLIC KEY BLOCK-----

Sunday, August 22, 2010

Are Morals Axiomatic or Can We Reach Them Via Reason Alone?

     Today I should like to explore what I think is a failing of Rational Constructivism (the theorists of which refer to themselves as "anti-moralists); that we ought to only do those things we can reason out an explanation for, and avoid making decisions as to how to act based on base and vulgar superstition.  So what is the failing with this belief?  Well, where do you start reasoning from?  Since the topic is morality, let's take an appropriate question and see how Christian philosophy explains it and then see how Rational Constructivism answers it.

     Is murder wrong?  Why?

     Christian philosophy would answer this in a seemingly simplistic way -- that yes, it's wrong to murder because, essentially, the Bible tells us so.  If we are to take C. S. Lewis' anecdotal "common sense" approach, this is further backed up by nigh-instinctual human feelings, some specific "sense" almost akin to the physical ones, that is consistent and standard across humanity (and 'sense' seems to be a good analogy as some people seem to have relatively strong, weak, or no morality at all, much as each man's quality of sight and sound are rather relative).  More to the point, murder is wrong because the 10 commandments forbid it and Jesus' Golden Rule (under which all actions should be measured) says, "Do unto others as you would have them do unto you;" most of us would prefer not to be murdered, so in following this rule we do not in turn murder.

      Rationalists seem to find such an explanation insulting -- they would equate it to submitting oneself to, again, base and vulgar superstition; not doing one's own thinking.  Surely, an intellectual would have a more dignified explanation where belief is not an issue in complying...right?  To paraphrase a response I got from this inquiry, "Yes, because it does harm."

     So apparently, I've been had.  I thought this guy was a rationalist and an atheist, yet here he is, adopting a moral that says "do no harm" as an axiom.  I asked "and why should we do no harm?" but he said he had already answered my question and intimated that further questioning was a sign of obstinacy on my part.

     Must we be left to our own to determine how a true Rational Constructivist would frame his argument?  I suppose we shall have to make as honest an attempt as can be made; and do correct me if the following conjecture mischaracterizes in any way, shape, or form, the philosophies of pure rationalism.

     Plato put forward one tool we might use:  "Act for the greater good."  But then, what is the greater good?  If we deign to turn to the public opinion on the matter -- assuming that surely, the public must know what's in their best interests, right? -- we get an inconsistent set of answers which varies temporally and regionally.  You might think inflicting pain was bad, right?  Not always -- De Sade, Sartre, and any number of ascetics (especially Buddhists) seem to value pain and suffering.  Of course, even had we found a consistent public opinion which held sway, we would then be left with the issue of explaining why the public opinion should form an axiom from which to build our arguments.

     Insomuch as most Rationalists tend to view themselves as men of science, which consists largely of divining how things work by observation and experiment, we ought to expect them to abhor sophistry and relativism since neither mathematics nor science work without some basic qualities of consistency and immutability.  (For example, if we define ourselves some numerical representations for counting in base ten, 1 + 1 should always be 2; it can't sometimes be 3 and sometimes be 0).  But yet, that seems to be what we're left with with a purely Rational approach.  We cannot apparently conclude what is good and what is bad without adopting some axiom on its face value.

Thursday, June 17, 2010

Passing Thought: Applying Computer Science Theory to Economic Theory

     So I have been reading The Collected Works of F. A. Hayek Volume 1:  The Fatal Conceit - The Errors of Socialism.  Haven't quite finished the first chapter, even but it brought some interesting thoughts that I wanted to write down before I forgot them.

-- Hayek makes a reference back to Adam Smith's discussion of basic supply and demand, "the invisible hand" and all... I got to thinking, maybe one of the reasons our economy does so well at what it does (with pricing serving as an indicator that serves to automatically adjusts supply and demand to prevent overproduction and overconsumption) is essentially a form of information hiding and modularity.

I suppose I should explain those terms.  Information hiding is best explained in terms of functions and arguments.  For a programmer, when you're making use of another programmer's function, your usual concern is what the function returns and what arguments are required in what order.  If you should decide to tool around with this other programmer's code without understanding how and why he programmed it the way he did, you will almost certainly end up with a function that is less efficient - and worse, you may break the function altogether.  Thus, there is a need to prevent the first programmer from changing the second programmer's code.  I won't bore you with the variety of methods how you might go about this in an object-oriented context, but I think you get the concept.

Modularity fits along the same lines -- basically it's the concept of breaking up a program from one big "main" function into a bunch of smaller ones; each usually accomplishing a very simple, easy-to-define task.  Under these circumstances it is much easier to debug a malfunctioning program because you can usually narrow down the function that is problematic and fix it accordingly.

Now, how does this all fit in with economics?  Well in early times, and even today, the consumer rarely knows how a particular product arrived at a given store.  He usually doesn't know how it was manufactured, sometimes he doesn't even know all the contents!  My thought is this: what if this not knowing is part of why our market system works so well?  And if that is so, isn't it all the more reason command economies (such as Socialism/Fascism/Communism/Mercantilism/Absolutism/etc) rarely if ever produce positive results (nevermind trying to get results better than what the market system provides)?

Let me know in the comments what you think of the idea. -- I'll go back to reading.

Wednesday, June 16, 2010

Iterated Circles - Mod of Sierpenski Square program

/* CMPT 300X  Chaos  Working with Fractals: Iterated Circle
 *
 * rewrite of Sierpinski Square code to iterate a circular fractal
 Author: Daniel Tanner
 *Note you can mess around with the code here a bit to avoid printing circles inside each other to generate a different fractal pattern (which I kinda like better but... eh).
 */

import javax.swing.JFrame;     //imports for the frame
import java.awt.*;         //imports the colour
import java.awt.Graphics;    //imports the graphics
import java.util.Random;  // imports the random class for random colour

import javax.swing.JPanel;

public class IteratedCircle extends JPanel
{
  public Graphics g;
  public Color c =Color.WHITE; // set colour to white to create the blanks
  public Random r = new Random();
   
  public static void main (String[]args)
  {
     JFrame SS = new JFrame("Drawing with Recursion");
     SS.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     SS.setVisible(true);   //Show the first drawing.
     IteratedCircle S = new IteratedCircle();  //call default constructor (not written);
     SS.setBackground(Color.BLACK);
     SS.add(S);
     SS.setSize(500, 500);  //(width ,height )   */

    //new SFrame();  // call to the frame, program
  }

  public void paint(Graphics g)
  {
    this.g = g;
    // start recursion with first call to draw square
    drawCircle( getWidth() / 2, getHeight() / 2, getWidth() / 4);    
   }
 
  private void drawCircle ( int x, int y ,int radius)
  {
      if (radius > 3) //control when to stop: when size is 2x2 pixels
      {      
      g.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
      g.drawRoundRect(x - radius / 2, y - radius / 2, radius, radius, radius * radius, radius / 2);
      drawCircle((int)(x + radius * .75), y, radius / 2);  //draws and fill the square, bigger one
      drawCircle((int)(x - radius * .75), y, radius / 2);
      drawCircle(x, (int)(y + radius * .75), radius / 2);
      drawCircle(x, (int)(y - radius * .75), radius / 2);
      //repaint();
      }
  }
 
  private void drawUpCircle( int x, int y ,int radius)
  {
      if (radius > 1) //control when to stop: when size is 2x2 pixels
      {      
      g.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
      g.drawRoundRect(x - radius / 2, y - radius / 2, radius, radius, radius * radius, radius / 2);
      drawUpCircle(x, (int)(y + radius * .75), radius / 2);
      drawRightCircle((int)(x + radius * .75), y, radius / 2);
      drawLeftCircle((int)(x - radius * .75), y, radius / 2);
      //repaint();
      }
  }
 
  private void drawDownCircle( int x, int y ,int radius)
  {
      if (radius > 1) //control when to stop: when size is 2x2 pixels
      {      
      g.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
      g.drawRoundRect(x - radius / 2, y - radius / 2, radius, radius, radius * radius, radius / 2);
      drawDownCircle(x, (int)(y - radius * .75), radius / 2);
      drawRightCircle((int)(x + radius * .75), y, radius / 2);
      drawLeftCircle((int)(x - radius * .75), y, radius / 2);
      //repaint();
      }
  }
 
  private void drawLeftCircle( int x, int y ,int radius)
  {
      if (radius > 1) //control when to stop: when size is 2x2 pixels
      {      
          g.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
      g.drawRoundRect(x - radius / 2, y - radius / 2, radius, radius, radius * radius, radius / 2);
      drawUpCircle(x, (int)(y + radius * .75), radius / 2);
      drawDownCircle(x, (int)(y - radius * .75), radius / 2);
      drawLeftCircle((int)(x - radius * .75), y, radius / 2);
      //repaint();
      }
  }
 
  private void drawRightCircle( int x, int y ,int radius)
  {
      if (radius > 1) //control when to stop: when size is 2x2 pixels
      {      
          g.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
      g.drawRoundRect(x - radius / 2, y - radius / 2, radius, radius, radius * radius, radius / 2);
      drawUpCircle(x, (int)(y + radius * .75), radius / 2);
      drawRightCircle((int)(x + radius * .75), y, radius / 2);
      drawDownCircle(x, (int)(y - radius * .75), radius / 2);
      //repaint();
      }
  }
}//end of class

The Dragon Curve

/*
 * Author: Daniel Tanner
 * Dragon Curve Program
 *
 * This program runs a recursive program to keep replacing a given
 * string such as "f" with "f+h" and "h" with "f-h",
 *  and after a certain number of said recursions, translates that
 *  string into a physical display.  The result is known as the
 *  Dragon Curve.
 */

import java.awt.*;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class DragonCurve extends JPanel {
 
 public Graphics g1;
 public Color c =Color.WHITE; // set colour to white to create the blanks
 public Random r = new Random();

 public static double degToRad(int deg) { //degree to radian conversion
  return deg * Math.PI / 180;
 }


 //paint method is automatically called for us by tree recursive (will be called 4 times! Once for each call to drawFractal
 public void paint(final Graphics g) {
  this.g1 = g;
  g1.setColor(c);
  int numRecursions = 14;
  double startAngle = degToRad(0);
  int distance = 3;
   //First call to do the drawing, this call draws the trunk: start(X,Y) at base, angle 0, len calculated)
  drawCurve(getWidth() / 2, getHeight() / 2, numRecursions, startAngle, distance);  //first call
     //System.out.println("in paint, number of calls to drawFractal is " + count +"\n");
   }

 //dragon curve method -- starts at the middle and applies rules to curve
 public void drawCurve(int x0, int y0, int numRecursions, double startAngle, int distance)
 {
    String dragonString = "f";
    for(int i = 0; i < numRecursions; i++)
    {
        String tempString = "";
        for(int j = 0; j < dragonString.length(); j++)
        {    //replace the f with f + h
            if(dragonString.charAt(j) == 'f')
                tempString += "f-h";
            else if(dragonString.charAt(j) == 'h')
                tempString += "f+h";
            else
                tempString += dragonString.charAt(j);
        }
        dragonString = tempString;
    }
    System.out.println(dragonString);
    //now draw the image
    for(int index = 0; index < dragonString.length(); index++)
    {
        if(dragonString.charAt(index) == 'f' || dragonString.charAt(index) == 'h')
        {
            g1.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
            int x1 = (int)(x0 + distance * Math.cos(startAngle));
            int y1 = (int)(y0 + distance * Math.sin(startAngle));
            g1.drawLine(x0, y0, x1, y1);
            x0 = x1; y0 = y1;
        }
        else if(dragonString.charAt(index) == 'g')
        {
            g1.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
            int x1 = (int)(x0 + distance * Math.cos(startAngle));
            int y1 = (int)(y0 + distance * Math.sin(startAngle));
            x0 = x1; y0 = y1;
        }
        else if(dragonString.charAt(index) == '+')
            startAngle = startAngle - Math.PI / 2.0;
        else if(dragonString.charAt(index) == '-')
            startAngle = startAngle + Math.PI / 2.0;
    }
 }

 //main method
 public static void main(String args[]) {
   // System.out.println("count begins with at " + count +"\n");
  JFrame FF = new JFrame("Drawing the Dragon Curve");
  FF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  FF.setVisible(true);   //Show the first drawing.
  DragonCurve F = new DragonCurve();  //call default constructor (not written); F is the Tree.
  FF.setBackground(Color.BLACK);
  FF.add(F);
  FF.setSize(1000, 1000);  //(width 1200,height 1000)   
 }
}

Chaos Program - Julia Orbits

/*Author: Daniel Tanner
 *Julia Orbits Display Program
 *This program displays all the orbit diagrams for a given julia set
 *(which the user can change by clicking on the viewing window)
 *
 *Basically displaying a line following the points when you take a
 *pair of starting values for a complex number 'c' (IE, x + yi), plug
 *it into the function (z^2 + c) where z is the starting point, and then
 *plug the result back into the function until the result is > 2
 */

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class JuliaOrbit extends JPanel implements MouseListener, WindowListener {
 
 public Graphics g1;
 public Color c =Color.WHITE; // set colour to white to create the blanks
 public Random r = new Random();
 private double cX = .360248, cY = .100376;

 public static double degToRad(int deg)
 { //degree to radian conversion
  return deg * Math.PI / 180;
 }


 //paint method is automatically called for us by tree recursive (will be called 4 times! Once for each call to drawFractal
 public void paint(Graphics g)
 {
  this.g1 = g;
  g1.setColor(c);
  double initX, initY;
   //First call to do the drawing, this call draws the trunk: start(X,Y) at base, angle 0, len calculated)
  for(initX = -2.0; initX <= 2.0; initX += 0.01)
  {
      for(initY = -2.0; initY <= 2.0; initY += 0.01)
      {
          drawJuliaOrbit(cX, cY, initX, initY);  //first call
          g1.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
      }
  }
 }

 //dragon curve method -- starts at the middle and applies rules to curve
 public void drawJuliaOrbit(double cX, double cY, double initX, double initY)
 {
    int m0 = (int)((initX + 1.0) * getWidth() / 2);
    int n0 = (int)((1.0 - initY) * getHeight() / 2);
   
    int iterations = 0;
    double q = Math.sqrt(initX * initX + initY * initY);
    while(q < 2 && iterations < 35)
    {
        iterations++;
        double y1 = 2.0 * (initX * initY);
        double x1 = (initX * initX) + -(initY * initY);
        initX = x1 + cX;
        initY = y1 + cY;
        int m1 = (int)((initX + 2.0) * getWidth() / 4);
        int n1 = (int)((2.0 - initY) * getHeight() / 4);
        g1.drawLine(m0, n0, m1, n1);
        q = Math.sqrt(initX * initX + initY * initY);
        m0 = m1; n0 = n1;
    }
 }

 //main method
 public static void main(String args[]) {
   // System.out.println("count begins with at " + count +"\n");
  JFrame FF = new JFrame("Drawing the Julia Orbit");
  FF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  FF.setVisible(true);   //Show the first drawing.
  JuliaOrbit F = new JuliaOrbit();  //call default constructor (not written); F is the Tree.
  FF.setBackground(Color.BLACK);
  FF.addMouseListener(F);
  FF.add(F);
  FF.setSize(200, 200);  //(width 1200,height 1000)   
 }

 public void mousePressed(MouseEvent e) { }

 public void mouseReleased(MouseEvent e)
 {
     if(e.getButton() == MouseEvent.BUTTON1)
     {
         cX = Double.parseDouble(JOptionPane.showInputDialog("Enter a new cX value:"));
         cY = Double.parseDouble(JOptionPane.showInputDialog("Enter a new cY value:"));
         this.repaint();
     }
 }

 public void mouseEntered(MouseEvent e) { }

 public void mouseExited(MouseEvent e) { }

 public void mouseClicked(MouseEvent e) {
 }


@Override
public void windowActivated(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}


@Override
public void windowClosed(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}


@Override
public void windowClosing(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}


@Override
public void windowDeactivated(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}


@Override
public void windowDeiconified(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}


@Override
public void windowIconified(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}


@Override
public void windowOpened(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}
}

Tuesday, April 13, 2010

Chat Server (final version)

/** Chat Server
Authors: Daniel J. Tanner and Jon Fidler
March 29th, 2010
CMPT 352 - Networking

This program implements the Spring 2010 Networking class' Chat Protocol
**/

import java.io.*;
import java.net.*;
import java.util.*;


public class ChatServer
{
    //constants & globals
    public static final int PORT = 2222;
    private static ChatServerSubject buffer = null;
   
   
    public static void main(String[] args) throws java.io.IOException
    {
        //load everything up
        buffer = new ChatServerSubject();
       
        //Create socket
        ServerSocket sock = null;
        try
        {
            //establish socket
            sock = new ServerSocket(PORT);
           
            while(true)
            {
                Socket client = sock.accept();
                //debug testing
                InetAddress ipAddr = client.getInetAddress();
                System.out.print(ipAddr.getHostAddress() + " : ");
                System.out.println(client.getPort() + " connected.");
                Thread worker = new Thread(new Connection(client, buffer));
               
                worker.start();
            }
        }
        //catch any errors opening sockets
        catch(IOException ioe)
        {
            System.err.println(ioe);
            System.exit(0);
        }
       
        finally
        {
            //close streams
            if(sock != null)
                sock.close();
        }
    }
   
    //getUserList function - returns a pointer to the user List
    public static Vector<String> getUserList() {return buffer.getUserList();}
}

/** ChatServerSubject object
-- implementation of the Subject class, containing the user list, an observer list, and the message buffer
-- This class will notify each child thread of the server whenever a change is made on either of these 2 objects.
Authors:  Jon Fidler & Daniel Tanner
March 31st, 2010
CMPT 352 - Networking
*/
import java.util.*;
import java.net.*;
import java.awt.*;

public class ChatServerSubject extends Observable
{
    //members
    private Vector<String> userList;
    private Vector<MessageObject> messageBuffer;
    private String removedUser;
   
    //flags
    /* whatHappened flag = int representing the state of the object.
    0 = nothing's changed
    1 = user added
    2 = user removed
    3 = message added
    */
    private int whatHappened;
   
    //constructors
    public ChatServerSubject()
    {
        userList = new Vector<String>();
        messageBuffer = new Vector<MessageObject>();
        removedUser = "NOBODY";
        whatHappened = 0;
    }
   
    /** userList changing functions
    */
    //add a user
    public void addUser(String userName)
    {
        userList.add(userName);
       
        //set flags
        whatHappened = 1;
        setChanged();
        notifyObservers();
    }
   
    //remove a user from the list
    public void removeUser(String userName)
    {
        removedUser = userName;
        userList.remove(userName);
       
        //set flags
        whatHappened = 2;
        setChanged();
        notifyObservers();
    }
   
    //check if a user is on the list or not
    public boolean userExists(String userName)
    {
        return userList.contains(userName);
    }
   
    //get user list
    public Vector<String> getUserList(){return userList;}
   
    //get the name of the user who just disconnected
    public String getDCedUser() {return removedUser;}
   
    //returns the last user on the list (most recently added user
    public String getNewUser() {return userList.lastElement();}
   
    /**Message Buffer functions
    */
    //get message function
    public MessageObject getMessage() {return messageBuffer.firstElement();}
   
    //add message function
    public void addMessage(MessageObject message)
    {
        messageBuffer.add(message);
        whatHappened = 3;
        setChanged();
        notifyObservers();
    }
   
    //remove a message
    public void removeMessage(MessageObject message)
    {
        messageBuffer.remove(message);
    }
   
    /* Flag checking functions*/
    public boolean userAdded()
    {
        if(whatHappened == 1)
            return true;
        return false;
    }
   
    public boolean userRemoved()
    {
        if(whatHappened == 2)
            return true;
        return false;
    }
   
    public boolean messageAdded()
    {
        if(whatHappened == 3)
            return true;
        return false;
    }
}

/** Connection Class for threaded Chat Server
Daniel Tanner & John Fidler
CMPT 352 - Computer Networking
March 29th, 2010
 */

import java.net.*;
import java.io.*;
import java.text.*;
import java.util.*;

public class Connection implements Runnable
{
    //create variables
    private Socket    client;
    private ChatServerSubject buffer;
    private Handler handler = new Handler();

    public Connection(Socket client, ChatServerSubject buffer)
    {
        this.client = client;
        this.buffer = buffer;
    }

    //Separate thread
    public void run()
    {
        try
        {
            handler.process(client, buffer);
        }
       
        catch (java.io.IOException ioe)
        {
            System.err.println(ioe);
        }
    }
}

/**
Daniel Tanner & Jon Fidler
CMPT 352 - Computer Networking
March 29th, 2010
Handler class for threaded Chat Server
 */

import java.net.*;
import java.lang.Object.*;
import java.util.*;
import java.text.*;
import javax.activation.*;
import java.io.*;
import java.util.regex.Pattern;

public class Handler implements Observer
{       
    //Create variables
    private BufferedReader fromClient = null;
    private BufferedOutputStream toClient = null;
    private ChatServerSubject buffer = null;
    private String myUserName = null;
    private String command = null;
    private boolean connectedProperly = false;
    private static Pattern alphaNum = Pattern.compile("^[A-Za-z0-9\\*]+$");

    //This method invoked as a separate thread
    public void process(Socket client, ChatServerSubject buffer) throws IOException
    {   
        //set up the method
        this.buffer = buffer;
       
        //try block for opening streams and getting hostname
        try
        {
            //open Streams
            fromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
            toClient = new BufferedOutputStream(client.getOutputStream());       
       
            //initial connection state
            command = fromClient.readLine();
            command = command.toLowerCase();
            if(!command.equalsIgnoreCase("connect"))
            {
                error("Bad Request.  Please input a proper command.", 2);
                return;
            }
           
            //get username, check against userList
            myUserName = fromClient.readLine();
            myUserName = myUserName.toUpperCase();
            if(buffer.userExists(myUserName))
            {
                error("Duplicate Handle.  Please try another name.", 1);
                return;
            }
           
            //check that username is within bounds
            if(!(myUserName.length() <= 16 && alphaNum.matcher(myUserName).matches()))
            {
                error("Invalid handle.  Handle must be an alphanumeric string with size less than or euqal to 16.", 3);
                return;
            }
            connectedProperly = true;
           
            //add username to userList
            buffer.addUser(myUserName);
            buffer.addObserver(this);
           
            //print userList to client
            printUserList();
           
            //listen for commands
            do
            {
                command = fromClient.readLine();
                command = command.toUpperCase();
               
                //getHandles command
                if(command.equalsIgnoreCase("gethandles"))
                    printUserList();
               
                //Post command
                else if(command.equalsIgnoreCase("post"))
                    constructMessage();
               
                //invalid command
                else if(!command.equalsIgnoreCase("disconnect"))
                    error("Invalid request.  Please input a proper command.", 2);
            }
            while(!command.equalsIgnoreCase("disconnect"));
        }
       
        catch(IOException ioe)
        {
            System.err.println(ioe);
            return;
        }
       
        finally
                {
                    //disconnection state
                    if(connectedProperly)
                    {
                            buffer.deleteObserver(this);
                            buffer.removeUser(myUserName);
                    }
                    // close streams and socket
                    if (fromClient != null)
                        fromClient.close();
                    if (toClient != null)
                        toClient.close();
                    if (client != null)
                        client.close();
                }
    }
   
    //broadcast method - this method is the basic broadcasting method
    //it assumes that we're sending a public message
    private void broadcast(MessageObject message) throws IOException
    {
        toClient.write("posted\n".getBytes());
        toClient.write((message.getFromUser() + "\n").getBytes());
        toClient.write("public\n".getBytes());
        toClient.write((message.getMessage() + "\n").getBytes());
        toClient.flush();
    }
   
    //private message broadcast method
    private void privateMessage(MessageObject message) throws IOException
    {
        toClient.write("posted\n".getBytes());
        toClient.write((message.getFromUser() + "\n").getBytes());
        toClient.write("private\n".getBytes());
        toClient.write((message.getMessage() + "\n").getBytes());
        toClient.flush();
    }
   
    //connected/disconnected message
    private void userConnected(String userName, boolean connected) throws IOException
    {
        if(connected)
            toClient.write("connected\n".getBytes());
        else
            toClient.write("disconnected\n".getBytes());
        toClient.write((userName + "\n").getBytes());
        toClient.flush();
    }
   
    //Error message
    private void error(String errorMessage, int errorNum) throws IOException
    {
        toClient.write("error\n".getBytes());
        toClient.write((errorNum + "\n").getBytes());
        toClient.write((errorMessage + "\n").getBytes());
        toClient.flush();
    }
   
    //Print user list function
    private void printUserList() throws IOException
    {
        Vector<String> currentUserList = new Vector<String>(buffer.getUserList());
        toClient.write("handles\n".getBytes());
        toClient.write((currentUserList.size() + "\n").getBytes());
        for(int index = 0; index < currentUserList.size(); index++)
            toClient.write((currentUserList.get(index) + "\n").getBytes());
        toClient.flush();
    }
   
    //CreateMessage method - goes to this state after receiving the post command from the user
    private void constructMessage() throws IOException
    {
        MessageObject newMessage = new MessageObject();
        newMessage.setFromUser(myUserName);
        String temp;
       
        //read the toUser
        temp = fromClient.readLine();
        temp = temp.toUpperCase();
        if(!(alphaNum.matcher(temp).matches() && temp.length() <= 16))
        {
            error("Invalid username entered.  Try again!.", 3);
            return;
        }
        if(!buffer.userExists(temp) && !temp.equalsIgnoreCase("*"))
        {
            error("User not found.", 4);
            return;
        }
        newMessage.setToUser(temp);
           
           
        //read the message and check to make sure it's within bounds
        temp = fromClient.readLine();
        if(temp.length() > 1024)
        {
            error("Message too Long", 5);
            return;
        }
        newMessage.setMessage(temp);
        buffer.addMessage(newMessage);
    }
   
    //update function - this is the observer functionality implemented
    //it will check the flags when the subject has changed, and act appropriately
    public void update(Observable o, Object arg)
    {
        try
        {
            //check if a user was added or removed
            if(buffer.userAdded())
                userConnected(buffer.getNewUser(), buffer.userAdded());
            else if(buffer.userRemoved())
                userConnected(buffer.getDCedUser(), buffer.userAdded());
                       
            //here's the routine when we get a new message
            else if(buffer.messageAdded())
            {
                MessageObject newMessage = buffer.getMessage();
                //check if it's a private message
                if(newMessage.getToUser().equals(myUserName))
                    privateMessage(newMessage);
               
                //now check if it's a broadcast and not from me
                else if(newMessage.getToUser().equals("*"))
                    broadcast(newMessage);
               
                //now decrement and check if the counter is at 0, remove from the list if it is
                newMessage.viewed();
                if(newMessage.getCounter() == 0)
                    buffer.removeMessage(newMessage);
            }
        }
        catch(IOException ioe)
        {
            System.err.println(ioe);
            command = "disconnect";
            return;
        }
           
    }
}

/**
BufferKeyEntry class

Contain fields to put into the key of the message buffer
The value will be the unformatted message

Members of the BufferEntry are as follows:

-Who sent the message (so we don't echo it back)

-A non-static counter which will tell us when all the threads have sent the message
so we know when to remove the message from our buffer.

-Who the message is to (* for broadcasts)
*/

/**
Authors: Daniel Tanner & Jon Fidler
March 29th, 2010
CMPT 352 - Networking
*/

import java.net.*;
import java.io.*;
import java.text.*;
import java.util.*;

public class MessageObject
{
    //create variables
    private String toUser;
    private String fromUser;
    private int counter;
    private String message;
   
    //constructor
    MessageObject()
    {
        counter = ChatServer.getUserList().size();
        toUser = null;
        fromUser = null;
        message = null;
    }
   
    //copy constructor
    MessageObject(MessageObject copy)
    {
        this.toUser = copy.toUser;
        this.fromUser = copy.fromUser;
        this.counter = copy.counter;
        this.message = copy.message;
    }
       
    //Constructor with arguments
    MessageObject(String toUser, String fromUser, String message)
    {
        counter = ChatServer.getUserList().size();
        this.toUser = toUser;
        this.fromUser = fromUser;
        this.message = message;
    }
   
    //get functions
    int getCounter() {return counter;}
    String getToUser() {return toUser;}
    String getFromUser() {return fromUser;}
    String getMessage() {return message;}
   
    //set functions
    void setToUser(String toUser) {this.toUser = toUser;}
    void setFromUser(String fromUser) {this.fromUser = fromUser;}
    void setMessage(String message) {this.message = message;}
   
    //viewed function - This function will decrement the counter
    void viewed() {counter--;}
   
    //equals function
    boolean equals(MessageObject rhs)
    {
        if(toUser.equals(rhs.toUser) && fromUser.equals(rhs.fromUser) && counter == rhs.counter && message.equals(rhs.message))
            return true;
        else
            return false;
    }
}